| |
oracle操纵数据的最好工具或者应用软件么?答案就在于通过操纵你想得到什么。数据可以通过操纵语言进行转化,也可以通过字符串或者数字型操纵进行转换。为了分清操作的类型,我们可以说说在dml的范围内存储的数据,什么样的数据是如何输出并显示给用户的。举个关于日其的简单例子,存储的数据可以被强制转换成许多方式。比如2007年3月8日可以输出成03/08/2007,仅仅取决于你或者用户想看到什么样的结果。
这篇文章的关注点就是什么样的数据被存储,什么样的数据被显示出来以及你是如何得到它们的。关于这一点围绕着字符串/数字型操纵的问题。加入你有一个应用软件能够通过互联网使用户能够调查或者提供商家的优待券。对于你的检验者来说,不管是id号还是帐号都是很常见的,在点击提交一项网上调查表后,会返回一个含有以名字-值成对出现的链接。
另一个这种“传送返回数据”传送机制的作用就是验证或者限制使用奖励的优待券。这种券不管是纸制式的还是电子式的,通常是以数字形式展现出来并且非常常见,数字也很大。数字很大以至于很难伪造或者假冒数字因为数字的密度能够被变稀疏。发行一百万的优待券条码从1,000,000 到,999,999,你只有一个密度。而使用的范围从77,000,000,000 到78,000,000,000使得找到一个正确的优待券号码相当于在一个甘草堆中寻找一根针。
但是问题或者约束就是在url(限制255或者256个字符)中返回一个22位的数字条码需要消耗很多宝贵的空间。我们需要的方法是能将大数缩短。该方法能够使我们达到这一点。
一种方法就是改变数字的基数。如果你能够把司10基数的数字转换成36基数的数字,你就能节省一些空间。利oracle如何实现这种转换呢?
-->create or replace function gen_barcode36 (i_coupon_number number) return varchar2 is v_number number; v_curval number; v_curinc number := power(36,14); v_true number := 0 ; v_pos number := 15; v_dec_count number := 0 ; v_pos_val number := 0 ; v_cur_num number := 0 ; v_test_num number := 0 ; v_new_num number := 0 ; v_cur_digit char := ''; v_new_val varchar2(15) := ''; begin v_number := i_coupon_number; while ( v_true = 0 ) loop v_curinc := v_curinc * 36; v_curval := v_number / v_curinc; if ( v_curval < 1 ) then v_true := 1; else v_pos := v_pos + 1; end if; end loop; v_dec_count := v_pos; v_new_val := null; v_cur_num := v_number; while ( v_dec_count > 0) loop v_pos_val := power(36,v_dec_count - 1); v_test_num := trunc(v_cur_num/v_pos_val); select decode(v_test_num,35,'z', 34,'y', 33,'x', 32,'w', 31,'v', 30,'u', 29,'t', 28,'s', 27,'r', 26,'q', 25,'p', 24,'o', 23,'n', 22,'m', 21,'l', 20,'k', 19,'j', 18,'i', 17,'h', 16,'g', 15,'f', 14,'e', 13,'d', 12,'c', 11,'b', 10,'a', 9,'9', 8,'8', 7,'7', 6,'6', 5,'5', 4,'4', 3,'3', 2,'2', 1,'1', '0') into v_cur_digit from dual; if ( v_new_val is not null ) then v_new_val := v_new_val || v_cur_digit; else v_new_val := v_cur_digit; end if; v_cur_num := v_cur_num - (v_pos_val * v_test_num); v_dec_count := v_dec_count - 1; end loop; return v_new_val; end gen_barcode36; /
一个不同的版本有一些输出附件,所以你能够看到数字是如何减少的。 sql> select gen_barcode36(7700000000000000000000) from dual;gen_barcode36(7700000000000000000000)-----------------------------------------------------1950zn8fqxjygowstarting with 7700000000000000000000position: 6140942214464815497216 current number: 1position 14 current value: 1position: 170581728179578208256 current number: 9position 13 current value: 19position: 4738381338321616896 current number: 5position 12 current value: 195position: 131621703842267136 current number: 0position 11 current value: 1950position: 3656158440062976 current number: 35position 10 current value: 1950zposition: 101559956668416 current number: 23position 9 current value: 1950znposition: 2821109907456 current number: 8position 8 current value: 1950zn8position: 78364164096 current number: 15position 7 current value: 1950zn8fposition: 2176782336 current number: 26position 6 current value: 1950zn8fqposition: 60466176 current number: 33position 5 current value: 1950zn8fqxposition: 1679616 current number: 19position 4 current value: 1950zn8fqxjposition: 46656 current number: 34position 3 current value: 1950zn8fqxjyposition: 1296 current number: 16position 2 current value: 1950zn8fqxjygposition: 36 current number: 24position 1 current value: 1950zn8fqxjygoposition: 1 current number: 32position 0 current value: 1950zn8fqxjygowfinal value: 1950zn8fqxjygow
这并非是通过含糊的方法达到安全的目的。虽然相关的奇怪的字符串会使得大多数用户揣摩不出来它所代表的含义。 一次一个,虽然数据操纵是好的,但是需要多久才能处理一百万个转换值呢?我们来建一个有三列的表。第一列是基数为10的数字,第二列是基数为36的数字,用上述的pl/sql代码将数字进行转换,第三列是为使用不同方法操纵数据的输出值。创建一个表,里面有一百万条数据。 sql> create table base362 (barcode number,3 plsql_ver varchar2(15),4 other_ver varchar2(15));table created.sql> create sequence barcode_seq start with 7700000000000000000000;sequence created.sql> begin2 for i in 1..1000000 loop3 insert into base36 (barcode) values (barcode_seq.nextval);4 end loop;5 end;6 /pl/sql procedure successfully completed.sql> commit;commit complete.sql> set timing onsql> update base36 set plsql_ver = gen_barcode36(barcode);1000000 rows updated.elapsed: 00:33:09.01
计算出每秒进行五百次更新。 可能会有比pl/sql方法更快的方法完成这项任务么?这个问题是个很好的例子,当使用比pl/sql更好的语言来转换数据是。这个在这种情况下一个更好的语言或方法就是使用java操作字符串以及使用嵌入的方法(tostring)。
您如何为一个数据库得到java代码? 首先,我们必须有一个java文件,有可用的ava代码在里面;其次,上传代码(源文件或者汇编版本)至数据库;再次,编译代码;最后一步就是将java代码包装成函数或者程序。函数调用oracle指定的对象,这个对象再调用java指定的对象。 源文件/java代码是相当简单的。 import java.math.biginteger;import java.lang.string;public class bcutils{public static string getbarcode36(string barcode10){string value = new string(barcode10);biginteger bigi = new biginteger(value.tostring());stringbuffer result = new stringbuffer(bigi.tostring(36));return result.tostring();}}导入源文件并编译它。创造一个功能函数/公共类。sql> create or replace function get_bc36(bc_10 varchar2)2 return varchar23 as language java name4 'bcutils.getbarcode36(java.lang.string) return java.lang.string';5 /function created.现在我们已经做好准备进行测试不同之处了。sql> update base36 set other_ver = get_bc36(barcode);1000000 rows updated.elapsed: 00:13:56.22
计算出每秒1200次,比pl/sql版的快两倍。为什么会这样?oracle承认世界上pl/sql不是最快的语言也不是最好的字符串处理方法。
在java开发指南的“java stored procedure steps”中有更正式的步骤清单。
结束语 pl/sql能够做好很多事情,但是其他语言能做的更好,这种“更好”是以速度进行检测的。如果你发现存储的数据为了输出显示的方式必须进行操作的话,不要担心,可以尝试oracle支持 。
原文链接:http://www.databasejournal.com/features/oracle/article.php/3664661
|
|