??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲一区二区三区高清不卡,亚洲线精品一区二区三区,亚洲欧洲日产国码无码久久99http://www.tkk7.com/iKingQu/category/8111.htmlJava菜鸟升?..zh-cnTue, 27 Feb 2007 10:22:51 GMTTue, 27 Feb 2007 10:22:51 GMT60[收藏]数据库连接、设计以及备份技巧集?/title><link>http://www.tkk7.com/iKingQu/articles/47124.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Fri, 19 May 2006 14:46:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/47124.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/47124.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/47124.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/47124.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/47124.html</trackback:ping><description><![CDATA[原文地址Q?a >http://java.ccidnet.com/art/297/20060326/489157_1.html</a><img src ="http://www.tkk7.com/iKingQu/aggbug/47124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-05-19 22:46 <a href="http://www.tkk7.com/iKingQu/articles/47124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]MySQL数据库优?/title><link>http://www.tkk7.com/iKingQu/articles/38162.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Wed, 29 Mar 2006 20:01:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/38162.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/38162.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/38162.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/38162.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/38162.html</trackback:ping><description><![CDATA[下决心开始学oracle?用mysql已经有不短的旉?今天写下q些是对自q一个mysql之旅的一个交代吧.以下仅仅是本人在使用mysqlq程中的一点个人的体会,也许存在许多U漏和错?q请指正!! <br /><br /><br /><br />首先,Z使一个系l更?最重要的部分就是基设计,不过有些东西是现有情况下无法逾越?比如说系l常见的瓉. <br /><br />我所能想到的: <br /><br />1:盘寻道能力,以高速硬?7200?U?,理论上每U寻?200?q是没有办法改变?优化的方法是----用多个硬?或者把数据分散存储. <br /><br />2:盘的读写速度,q个速度非常的快(限于本h的知识所?只知道在每秒几十甚至上百MB).q个更容易解?-可以从多个硬盘上q行d. <br /><br />3:cpu.cpu处理内存中的数据,当有相对内存较小的表?q是最常见的限制因? <br /><br />4:内存的限?当cpu需要超出适合cpu~存的数据时,~存的带宽就成了内存的一个瓶?--不过现在内存大的惊h,一般不会出现这个问? <br /><br />W二? <br /><br />(本h使用的是学校|站的linuxq_(Linux ADVX.Mandrakesoft.com 2.4.3-19mdk )) <br /><br />1:调节服务器参?<br /><br />用shell>mysqld-helpq个命o声厂一张所有mysql选项和可配置变量的表.输出以下信息: <br /><br />possible variables for option--set-variable(-o) are: <br /><br />back_log current value:5 //要求mysql能有的连接数?back_log指出在mysql暂停接受q接的时间内有多个q接h可以被存在堆栈中 <br /><br />connect_timeout current value:5 //mysql服务器在用bad handshake(不好译)应答前等待一个连接的旉 <br /><br />delayed_insert_timeout current value:200 //一个insert delayed在终止前{待insert的时?<br /><br />delayed_insert_limit current value:50 //insert delayed处理器将查是否有Mselect语句未执?如果?l箋前执行这些语?<br /><br />delayed_queue_size current value:1000 //为insert delayed分配多大的队 <br /><br />flush_time current value:0 //如果被设|ؓ?,那么每个flush_time 旉,所有表都被关闭 <br /><br />interactive_timeout current value:28800 //服务器在关上它之前在z交互连接上{待的时?<br /><br />join_buffer_size current value:131072 //用与全部q接的缓冲区大小 <br /><br />key_buffer_size current value:1048540 //用语索引块的~冲区的大小,增加它可以更好的处理索引 <br /><br />lower_case_table_names current value:0 // <br /><br />long_query_time current value:10 //如果一个查询所用时间大于此旉,slow_queried计数增?<br /><br />max_allowed_packet current value:1048576 //一个包的大?<br /><br />max_connections current value:300 //允许同时q接的数?<br /><br />max_connect_errors current value:10 //如果有多于该数量的中断连?阻止进一步的q接,可以用flush hosts来解?<br /><br />max_delayed_threads current value:15 //可以启动的处理insert delayed的数?<br /><br />max_heap_table_size current value:16777216 // <br /><br />max_join_size current value:4294967295 //允许d的连接的数量 <br /><br />max_sort_length current value:1024 //在排序blob或者text时用的字节数量 <br /><br />max_tmp_tables current value:32 //一个连接同时打开的时表的数?<br /><br />max_write_lock_count current value:4294967295 //指定一个?通常很小)来启动mysqld,使得在一定数量的write锁定之后出现read锁定 <br /><br />net_buffer_length current value:16384 //通信~冲区的大小--在查询时被重|ؓ该大?<br /><br />query_buffer_size current value:0 //查询时缓冲区大小 <br /><br />record_buffer current value:131072 //每个序扫描的连接ؓ其扫描的每张表分配的~冲区的大小 <br /><br />sort_buffer current value:2097116 //每个q行排序的连接分配的~冲区的大小 <br /><br />table_cache current value:64 //为所有连接打开的表的数?<br /><br />thread_concurrency current value:10 // <br /><br />tmp_table_size current value:1048576 //临时表的大小 <br /><br />thread_stack current value:131072 //每个U程的大?<br /><br />wait_timeout current value:28800 //服务器在关闭?之前的一个连接上{待的时?<br /><br /><br /><br />Ҏ(gu)自己的需要配|以上信息会对你帮助. <br /><br /><br /><br />W三: <br /><br />1:如果你在一个数据库中创建大量的?那么执行打开,关闭Q创??的操作就会很? <br /><br />2:mysql使用内存 <br /><br />a: 关键字缓存区(key_buffer_size)由所有线E共?<br /><br />b: 每个q接使用一些特定的U程I间.一个栈(默认?4k,变量thread_stack),一个连接缓冲区(变量net_buffer_length)和一个结果缓冲区(net_buffer_length).特定情况?q接~冲区和l果~冲动态扩大到max_allowed_packet. <br /><br />c:所有线E共享一个基存储?<br /><br />d:没有内存影射 <br /><br />e:每个做顺序扫描的h分配一个读~冲?record_buffer) <br /><br />f:所有联l均有一遍完成ƈ且大多数联结甚至可以不用一个时表完成.最临时的表是基于内存的(heap)?<br /><br />g:排序h分配一个排序缓冲区?个时表 <br /><br />h:所有语法分析和计算都在一个本地存储器完成 <br /><br />i:每个索引文g只被打开一?q且数据文g为每个ƈ发运行的U程打开一?<br /><br />j:Ҏ(gu)个blob列的表,一个缓冲区动态的被扩大以便读入blob?<br /><br />k:所有正在用的表的表处理器被保存在一个缓冲器中ƈ且作Z个fifo理. <br /><br />l:一个mysqladmin flush-tables命o关闭所有不在用的表ƈ且在当前执行的线E结束时标记所有在使用的表准备关闭 <br /><br />3:mysql锁定?<br /><br />mysql中所有锁定不会成为死? <br /><br />wirte锁定: <br /><br />mysql的锁定原?a:如果表没有锁?那么锁定;b否则,把锁定请求放入写锁定队列?<br /><br />read锁定: <br /><br />mysql的锁定原?a:如果表没有锁?那么锁定;b否则,把锁定请求放入读锁定队列?<br /><br /><br /><br />有时候会在一个表中进行很多的select,insert操作,可以在一个时表中插入行q且偶尔用时表的记录更新真正的?<br /><br />a:用low_priority属性给一个特定的insert,update或者delete较低的优先 <br /><br />b:max_write_lock_count指定一个?通常很小)来启动mysqld,使得在一定数量的write锁定之后出现read锁定 <br /><br />c:通过使用set sql_low_priority_updates=1可以从一个特定的U程指定所有的更改应该p低的优先U完?<br /><br />d:用high_priority指定一个select <br /><br />e:如果使用insert....select....出现问题,使用myisam?-----因ؓ它支持因为它支持q发的select和insert <br /><br />4:最基本的优化是使数据在盘上占据的I间最?如果索引做在最的列上,那么索引也最?实现Ҏ(gu): <br /><br />a:使用可能小的数据类?<br /><br />b:如果可能Q声明表列ؓNOT NULL. <br /><br />c:如果有可能用变成的数据cd,如varchar(但是速度会受一定的影响) <br /><br />d:每个表应该有可能短的主索引 <br /><br />e:创徏实需要的索引 <br /><br />f:如果一个烦引在头几个字W上有唯一的前~,那么仅仅索引q个前缀----mysql支持在一个字W列的一部分上的索引 <br /><br />g:如果一个表l常被扫?那么试图拆分它ؓ更多的表 <br /><br /><br /><br /><br /><br />W四?<br /><br />1:索引的?索引的重要性就不说?功能也不说了,只说怎么? <br /><br />首先要明所有的mysql索引(primary,unique,index)在b树中有存?索引主要用语: <br /><br />a:快速找到where指定条g的记?<br /><br />b:执行联结?从其他表索行 <br /><br />c:对特定的索引列找出max()和min()?<br /><br />dQ如果排序或者分l在一个可用键的最前面加前~Q排序或分组一个表 <br /><br />eQ一个查询可能被用来优化索|而不用访问数据文Ӟ如果某些表的列是数字型ƈ且正好是某个列的前缀Qؓ了更快,值可以从索引树中取出 <br /><br />Q:存储或者更新数据的查询速度 <br /><br /> grant的执行会E稍的减低效率. <br /><br /> mysql的函数应该被高度的优化.可以用benchmarkQloop_count,expression)来找出是否查询有问题 <br /><br /> select 的查询速度Q如果想要让一个selectQ.QwhereQ.Q更快,我能惛_的只有徏立烦引.可以在一个表上运行myisamchkQ-analyze 来更好的优化查询Q可以用myisamchkQ-sortQindexQ-sortQrecordsQ1来设|用一个烦引排序一个烦引和数据Q?<br /><br />Q:mysql优化where子句 <br /><br />3.Q:删除不必要的括号Q?<br /><br /> Q(a AND b) AND c OR (((a AND b) AND (a AND d))))>(a AND b AND c) OR (a AND b AND c AND d) <br /><br />3.2:使用常数 <br /><br /> Qa<b AND b=c) AND a=100 > b>5 AND b=c AND a=5 <br /><br />3.3:删除常数条g <br /><br />Qb>=5 AND b=5) OR (b=6 AND 5=5) OR (b=100 AND 2=3) > b=5 OR b=6 <br /><br />3.4:索引使用的常数表辑ּ仅计一?<br /><br />3.5Q在一个表中,没有一个where的count(*)直接从表中检索信?<br /><br />3.6:所有常数的表在查询中在M其他表之前读?<br /><br />3.7:对外联结表最好联l组合是试了所有可能性找到的 <br /><br />3.8Q如果有一个order by字句和一个不同的group by子句或者order by或者group by包含不是来自联结的第一个表的列Q那么创Z个时表 <br /><br />3.9:如果使用了sql_small_resultQ那么msyql使用在内存中的一个表 <br /><br />3.10:每个表的索引l查询ƈ且用跨少于3Q%的行的烦引. <br /><br />3.11在每个记录输出前Q蟩q不匚whaving子句的行 <br /><br /><br /><br />Q:优化left join <br /><br />在mysql中 a left join b按以下方式实?<br /><br />aQ表b依赖于表a  <br /><br />bQ表a依赖于所有用在left join条g的表Q除了bQ?<br /><br />cQ所有left join条g被移到where子句?<br /><br />dQ进行所有的联结优化Q除了一个表L在所有他依赖的表后读取.如果有一个@环依赖,那么发生错?<br /><br />eQ进行所有的标准的where优化 <br /><br />fQ如果在a中有一行匹配where子句Q但是在b中没有Q何匹配left join条gQ那么,在b中生成的所有设|ؓQUQL的一?<br /><br />gQ如果用left join来找出某些表中不存在的行q且在where部分有column_name IS NULL试(column_name为NOT NULL?Q那么,mysql在它已经扑ֈ了匹配left join条g的一行后Q将停止在更多的行后L <br /><br />Q:优化limit <br /><br />aQ如果用limit只选择一行,当mysql需要扫描整个表Ӟ它的作用相当于烦?<br /><br />bQ如果用limitQ与order byQmysql如果扑ֈ了第Q行Q将l束排序Q而不会排序正个表 <br /><br />cQ当l合limitQ和distinctӞmysql如果扑ֈ了第Q行Q将停止 <br /><br />dQ只要mysql已经发送了W一个#行到客户Qmysql放弃查?<br /><br />eQlimit 0一直会很快的返回一个空集合Q?<br /><br />fQ时表的大用limitQ计需要多空间来解决查询 <br /><br />Q:优化insert <br /><br />插入一条记录的是由以下构成Q?<br /><br />a:q接Q3Q?<br /><br />b:发送查询给服务器(Q) <br /><br />c:分析查询Q2Q?<br /><br />d:插入记录Q1*记录大小Q?<br /><br />eQ插入烦引(Q?索引Q?<br /><br />fQ关闭(Q) <br /><br />以上数字可以看成和L间成比例 <br /><br />改善插入速度的一些方法: <br /><br />6.1Q如果同时从一个连接插入许多行Q用多个值的insertQ这比用多个语句要快 <br /><br />6.2Q如果从不同q接插入很多行,使用insert delayed语句速度更快 <br /><br />6.3: 用myisamQ如果在表中没有删除的行Q能在selectQs正在q行的同时插入行 <br /><br />6.4: 当从一个文本文件装载一个表Ӟ用load data infileQ这个通常比insert?0 <br /><br />?<br /><br />6.5: 可以锁定表然后插入-Q主要的速度差别是在所有insert语句完成后,索引~冲Z被存入到盘一ơ.一般与有不同的insert语句那样多次存入要快Q如果能用一个单个语句插入所有的行,锁定׃需要.锁定也降低连接的整体旉Q但是对某些U程最大等待时间将上升Q例如: <br /><br />thread 1 does 1000 inserts <br /><br />thread 2,3 and 4 does 1 insert <br /><br />thread 5 does 1000 inserts <br /><br />如果不用锁定,Q,Q,Q将在1和5之前完成Q如果用锁定,Q,Q,Q,可能在Q和Q之后完成.但是整体旉应该快4Q%Q因为insertQ?updateQdelete操作在mysql中是很快的,通过为多于大U5ơ连l不断的插入或更C行的东西加锁Q将获得更好的整体性能Q如果做很多一行的插入Q可以做一个lock tablesQ偶随后做一个unlock tablesQ大U每Q0Q0行)以允许另外的U程存取表.q仍然将D获得好的性能Qload data infile对装载数据仍然是很快的. <br /><br />Z对load data infile和insert得到一些更快的速度Q扩大关键字~冲区. <br /><br />Q优化update的速度 <br /><br />它的速度依赖于被更新数据的大和被更新烦引的数量 <br /><br />使update更快的另一个方法是推迟修改Q然后一行一行的做很多修改.如果锁定表,做一行一行的很多修改比一ơ做一个快 <br /><br />Q优化delete速度 <br /><br />删除一个记录的旉与烦引数量成正比Qؓ了更快的删除记录Q可以增加烦引缓存的大小 <br /><br />从一个表删除所有行比删除这个表的大部分要快的多 <br /><br /><br /><br />W五?<br /><br />Q:选择一U表cd <br /><br />1.1静态myisam <br /><br />q种格式是最单且最安全的格式,它是盘格式中最快的Q速度来自于数据能在磁盘上被找到的难易E度Q当锁定有一个烦引和静态格式的东西是,它很单,只是行长度乘以数量.而且在扫描一张表Ӟ每次用磁盘读取来d常数个记录是很容易的Q安全性来源于如果当写入一个静态myisam文g时导致计机down 掉,myisamchk很容易指出每行在哪里开始和l束Q因此,它通常能收回所有记录,除了部分被写入的记录Q在mysql中所有烦引总能被重?<br /><br />1.2动态myisam <br /><br />q种格式每一行必L一个头说明它有多长Q当一个记录在更改期间变长Ӟ它可以在多于一个位|上l束Q能使用optimize tablename?myisamchk整理一张表Q如果在同一个表中有像某些varchar或者blob列那样存取/改变的静态数据,动态列Ud另外一个表以避免碎片. <br /><br />1.2.1压羃myisamQ用可选的myisampack工具生成 <br /><br />1.2.2内存 <br /><br />q种格式对小型/中型表很有用Q对拯Q创Z个常用的查找表到zheap表有可能加快多个表联l,用同h据可能要快好几倍时_ <br /><br />select tablename.a,tablename2.a from tablename,tablanem2,tablename3 where <br /><br />tablaneme.a=tablename2.a and tablename2.a=tablename3.a and tablename2.c!=0; <br /><br /><br /><br />Z加速它Q可以用tablename2和tablename3的联l创Z个时表Q因为用相同列(tablename1.aQ查找. <br /><br />CREATE  TEMPORARY  TABLE  test TYPE=HEAP <br /><br />SELECT <br /><br />tablename2.a as a2,tablename3.a as a3 <br /><br />FROM <br /><br />tablenam2,tablename3 <br /><br />WHERE <br /><br />tablename2.a=tablename3.a and c=0; <br /><br />SELECT tablename.a,test.a3 from tablename,test where tablename.a=test.a1; <br /><br />SELECT tablename.a,test,a3,from tablename,test where tablename.a=test.a1 and ....; <br /><br /><br /><br />1.3静态表的特?<br /><br />1.3.1默认格式Q用在表不包含varcharQblobQtext列的时?<br /><br />1.3.2所有的charQnumeric和decimal列填充到列宽?<br /><br />1.3.3非常?<br /><br />1.3.4Ҏ(gu)~冲 <br /><br />1.3.5Ҏ(gu)在down后重建,因ؓ记录位于固定的位|?<br /><br />1.3.6不必被重新组l(用myisamchkQ,除非是一个巨量的记录被删除ƈ且优化存储大?<br /><br />1.3.7通常比动态表需要更多的存储I间 <br /><br /><br /><br />1.4动态表的特?<br /><br />1.4.1如果表包含Q何varcharQblobQtext列,使用该格?<br /><br />1.4.2所有字W串列是动态的 <br /><br />1.4.3每个记录前置一个位Q?<br /><br />1.4.4通常比定长表需要更多的盘I间 <br /><br />1.4.5每个记录仅仅使用所需要的I间Q如果一个记录变的很大,它按需要被分成很多D,q导致了记录片 <br /><br />1.4.6如果用超q行长度的信息更新行Q行被分D. <br /><br />1.4.7在系ldown掉以后不好重Q因Z个记录可以是多段 <br /><br />1.4.8对动态尺寸记录的期望行长度是Q+Qnumber of columnsQ7Q/Q+(number <br /><br />of char columns)+packed size of numeric columns+length of strings +(number of <br /><br />NULL columns+7)/8 <br /><br />Ҏ(gu)个连接有Q个字节的惩|.无论何时更改引v记录的变大,都有一个动态记录被q接Q每个新q接臛_有2Q个字节Q因此下一个变大将可能在同一个连接中Q如果不是,有另外一个连接.可以用myisamchk Q恶毒检查有多少q接Q所有连接可以用myisamchk -r删除Q?<br /><br /><br /><br />1.5压羃表的特点 <br /><br />1.5.1一张用myisampack实用E序制作的只读表Q?<br /><br />1.5.2解压~代码存在于所有mysql分发中,以便使没有myisampack的连接也能读取用myisampack压羃的表 <br /><br />1.5.3占据很小的磁盘空?<br /><br />1.5.4每个记录被单独压~.一个记录的头是一个定长的Q1~~Q个字节Q这取决于表的最大记录.每列以不同的方式被压~.一些常用的压羃cd是: <br /><br /> a:通常Ҏ(gu)列有一张不同的哈夫D <br /><br /> b:后缀I白压羃 <br /><br /> c:前缀I白压羃 <br /><br />d:用|的数字用1位存?<br /><br />e:如果整数列的值有一个小范围Q列使用最的可能cd来存储.例如Q如果所有的值在Q到Q5Q之_一个bigint可以作ؓ一个tinyint存储 <br /><br /> g:如果列仅有可能值的一个小集合Q列cd被{换到enum <br /><br /> h:列可以用上面的压羃Ҏ(gu)的组?<br /><br />1.5.5能处理定长或动态长度的记录Q去不能处理blob或者text?<br /><br />1.5.6能用myisamchk解压~?<br /><br />mysql能支持不同的索引cdQ但一般的cd是isamQ这是一个树烦引ƈ且能_略的ؓ索引文g计算大小?key_length+4)*0.67Q在所有的键上的dQ?<br /><br />字符串烦引是I白压羃的。如果第一个烦引是一个字W串Q它可将压羃前缀如果字符串列有很多尾部空白或是一个总部能甬道全长的varchar列,I白压羃使烦引文件更.如果很多字符串有相同的前~Q?<br /><br />1.6内存表的特点 <br /><br />mysql内部的heap表用每偶溢出去的1Q0Q动态哈希ƈ且没有与删除有关的问题.只能通过使用在堆表中的一个烦引来用等式存取东西(通常用'Q'操作W) <br /><br />堆表的缺Ҏ(gu)Q?<br /><br />1.6.1惌同时使用的所有堆表需要够的额外内存 <br /><br />1.6.2不能在烦引的一个部分搜?<br /><br />1.6.3不能按顺序搜索下一个条目(卻I使用q个索引做一个order byQ?<br /><br />1.6.4mysql不能出在2个g间大概有多少行.q被优化器用是用来军_使用哪个索引的,但是在另一个方面甚至不需要磁盘寻?img src ="http://www.tkk7.com/iKingQu/aggbug/38162.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-30 04:01 <a href="http://www.tkk7.com/iKingQu/articles/38162.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]JDBCpd教程Q六Q?--可调用语?/title><link>http://www.tkk7.com/iKingQu/articles/36764.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Tue, 21 Mar 2006 19:44:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/36764.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/36764.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/36764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/36764.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/36764.html</trackback:ping><description><![CDATA[ <p> <span id="lzslqep" class="Title">JDBCpd教程Q六Q?--可调用语?</span> </p> <p>CallableStatement </p> <p>本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这本书是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版。?</p> <p> <br />7.1 概述 <br />CallableStatement 对象为所有的 DBMS 提供了一U以标准形式调用已储存过E的Ҏ(gu)。已储存q程储存在数据库中。对已储存过E的调用?CallableStatement 对象所含的内容。这U调用是用一U换码语法来写的Q有两种形式Q一UŞ式带l果参数Q另一UŞ式不带结果参敎ͼ有关换码语法的信息,参见W?4 节“语句”)。结果参数是一U输?(OUT) 参数Q是已储存过E的q回倹{两UŞ式都可带有数量可变的输入QIN 参数Q、输出(OUT 参数Q或输入和输出(INOUT 参数Q的参数。问号将用作参数的占位符?</p> <p>?JDBC 中调用已储存q程的语法如下所C。注意,Ҏ(gu)可C其间的内容是可选项Q方括号本nq不是语法的l成部䆾?</p> <p>{call q程名[(?, ?, ...)]} </p> <p>q回l果参数的过E的语法为:  </p> <p>{? = call q程名[(?, ?, ...)]} </p> <p>不带参数的已储存q程的语法类|  </p> <p>{call q程名} </p> <p>通常Q创?CallableStatement 对象的h应当知道所用的 DBMS 是支持已储存q程的,q且知道q些q程都是些什么。然而,如果需要检查,多种 DatabaseMetaData Ҏ(gu)都可以提供这L信息。例如,如果 DBMS 支持已储存过E的调用Q则 supportsStoredProcedures Ҏ(gu)返?trueQ?getProcedures Ҏ(gu)返回对已储存过E的描述?</p> <p>CallableStatement l承 Statement 的方法(它们用于处理一般的 SQL 语句Q,q承了 PreparedStatement 的方法(它们用于处理 IN 参数Q。CallableStatement 中定义的所有方法都用于处理 OUT 参数?INOUT 参数的输出部分:注册 OUT 参数?JDBC cdQ一?SQL cdQ、从q些参数中检索结果,或者检查所q回的值是否ؓ JDBC NULL?</p> <p> <br />7.1.1 创徏 CallableStatement 对象 <br />CallableStatement 对象是用 Connection Ҏ(gu) prepareCall 创徏的。下例创?CallableStatement 的实例,其中含有对已储存q程 getTestData 调用。该q程有两个变量,但不含结果参敎ͼ  </p> <p>CallableStatement cstmt = con.prepareCall( <br />"{call getTestData(?, ?)}"); </p> <p>其中 ? 占位Wؓ IN?OUT q是 INOUT 参数Q取决于已储存过E?getTestData?</p> <p> <br />7.1.2 IN ?OUT 参数 <br />?IN 参数传给 CallableStatement 对象是通过 setXXX Ҏ(gu)完成的。该Ҏ(gu)l承?PreparedStatement。所传入参数的类型决定了所用的 setXXX Ҏ(gu)Q例如,?setFloat 来传?float 值等Q?</p> <p>如果已储存过E返?OUT 参数Q则在执?CallableStatement 对象以前必须先注册每?OUT 参数?JDBC cdQ这是必需的,因ؓ某些 DBMS 要求 JDBC cdQ。注?JDBC cd是用 registerOutParameter Ҏ(gu)来完成的。语句执行完后,CallableStatement ?getXXX Ҏ(gu)取回参数倹{正的 getXXX Ҏ(gu)是ؓ各参数所注册?JDBC cd所对应?Java cdQ从 JDBC cd?Java cd的标准映见 8.6.1 节中的表Q。换a之, registerOutParameter 使用的是 JDBC cdQ因此它与数据库q回?JDBC cd匚wQ,?getXXX 之转换?Java cd?</p> <p>作ؓCZQ下qC码先注册 OUT 参数Q执行由 cstmt 所调用的已储存q程Q然后检索在 OUT 参数中返回的倹{方?getByte 从第一?OUT 参数中取Z?Java 字节Q?getBigDecimal 从第二个 OUT 参数中取Z?BigDecimal 对象Q小数点后面带三位数Q:  </p> <p>CallableStatement cstmt = con.prepareCall( <br />"{call getTestData(?, ?)}"); <br />cstmt.registerOutParameter(1, java.sql.Types.TINYINT); <br />cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3); <br />cstmt.executeQuery(); <br />byte x = cstmt.getByte(1); <br />java.math.BigDecimal n = cstmt.getBigDecimal(2, 3); </p> <p>CallableStatement ?ResultSet 不同Q它不提供用增量方式索大 OUT 值的Ҏ(gu)机制?</p> <p> <br />7.1.3 INOUT 参数 <br />既支持输入又接受输出的参敎ͼINOUT 参数Q除了调?registerOutParameter Ҏ(gu)外,q要求调用适当?setXXX Ҏ(gu)Q该Ҏ(gu)是从 PreparedStatement l承来的Q。setXXX Ҏ(gu)参数D|ؓ输入参数Q?registerOutParameter Ҏ(gu)它?JDBC cd注册出参数。setXXX Ҏ(gu)提供一?Java |而驱动程序先把这个D{换ؓ JDBC |然后它送到数据库中?</p> <p>q种 IN 值的 JDBC cd和提供给 registerOutParameter Ҏ(gu)?JDBC cd应该相同。然后,要检索输出|p用对应的 getXXX Ҏ(gu)。例如,Java cd?byte 的参数应该用方?setByte 来赋输入倹{应该给 registerOutParameter 提供cd?TINYINT ?JDBC cdQ同时应使用 getByte 来检索输出?Q第 8 节“JDBC ?Java cd之间的映”将l出详细信息和类型映表Q?</p> <p>下例假设有一个已储存q程 reviseTotalQ其唯一参数?INOUT 参数。方?setByte 把此参数设ؓ 25Q驱动程序将把它作ؓ JDBC TINYINT cd送到数据库中。接着QregisterOutParameter 该参数注册?JDBC TINYINT。执行完该已储存q程后,返回一个新?JDBC TINYINT 倹{方?getByte 把q个新g?Java byte cd索?</p> <p>CallableStatement cstmt = con.prepareCall( <br />"{call reviseTotal(?)}"); <br />cstmt.setByte(1, 25); <br />cstmt.registerOutParameter(1, java.sql.Types.TINYINT); <br />cstmt.executeUpdate(); <br />byte x = cstmt.getByte(1); </p> <p>7.1.4 先检索结果,再检?OUT 参数 <br />׃某些 DBMS 的限ӞZ实现最大的可移植性,先检索由执行 CallableStatement 对象所产生的结果,然后再用 CallableStatement.getXXX Ҏ(gu)来检?OUT 参数?</p> <p>如果 CallableStatement 对象q回多个 ResultSet 对象Q通过调用 execute Ҏ(gu)Q,在检?OUT 参数前应先检索所有的l果。这U情况下Qؓ保Ҏ(gu)有的l果都进行了讉KQ必d Statement Ҏ(gu) getResultSet、getUpdateCount ?getMoreResults q行调用Q直C再有l果为止?</p> <p>索完所有的l果后,可?CallableStatement.getXXX Ҏ(gu)来检?OUT 参数中的倹{?</p> <p> <br />7.1.5 索作?OUT 参数?NULL ?<br />q回?OUT 参数中的值可能会?JDBC NULL。当出现q种情ŞӞ对 JDBC NULL D行{换以?getXXX Ҏ(gu)所q回的gؓ null? ?falseQ这取决?getXXX Ҏ(gu)cd。对?ResultSet 对象Q要知道 0 ?false 是否源于 JDBC NULL 的唯一Ҏ(gu)Q是用方?wasNull q行。如?getXXX Ҏ(gu)d的最后一个值是 JDBC NULLQ则该方法返?trueQ否则返?flase。第 5 节“ResultSet”将l出详细信息。 ?</p> <br /> <br /> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630452</p> <img src ="http://www.tkk7.com/iKingQu/aggbug/36764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-22 03:44 <a href="http://www.tkk7.com/iKingQu/articles/36764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]JDBCpd教程Q五Q?--准备语句http://www.tkk7.com/iKingQu/articles/36762.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:32:00 GMThttp://www.tkk7.com/iKingQu/articles/36762.htmlhttp://www.tkk7.com/iKingQu/comments/36762.htmlhttp://www.tkk7.com/iKingQu/articles/36762.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36762.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36762.html

JDBCpd教程Q五Q?--准备语句

PreparedStatement

本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版。?


6.1 概述
?PreparedStatement 接口l承 StatementQƈ与之在两斚w有所不同Q?


PreparedStatement 实例包含已编译的 SQL 语句。这是使语句“准备好”。?
包含?PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN 参数的值在 SQL 语句创徏时未被指定。相反的Q该语句为每?IN 参数保留一个问P“?”)作ؓ占位W。每个问L值必d该语句执行之前,通过适当?setXXX Ҏ(gu)来提供。?

׃ PreparedStatement 对象已预~译q,所以其执行速度要快?Statement 对象。因此,多次执行?SQL 语句l常创徏?PreparedStatement 对象Q以提高效率?

作ؓ Statement 的子c,PreparedStatement l承?Statement 的所有功能。另外它q添加了一整套Ҏ(gu)Q用于设|发送给数据库以取代 IN 参数占位W的倹{同Ӟ三种Ҏ(gu) execute?executeQuery ?executeUpdate 已被更改以之不再需要参数。这些方法的 Statement 形式Q接?SQL 语句参数的Ş式)不应该用?PreparedStatement 对象?


6.1.1 创徏 PreparedStatement 对象
以下的代码段Q其?con ?Connection 对象Q创建包含带两个 IN 参数占位W的 SQL 语句?PreparedStatement 对象Q?

PreparedStatement pstmt = con.prepareStatement(
"UPDATE table4 SET m = ? WHERE x = ?");

pstmt 对象包含语句 "UPDATE table4 SET m = ? WHERE x = ?"Q它已发送给 DBMSQƈ为执行作好了准备?


6.1.2 传?IN 参数
在执?PreparedStatement 对象之前Q必设|每?? 参数的倹{这可通过调用 setXXX Ҏ(gu)来完成,其中 XXX 是与该参数相应的cd。例如,如果参数h Java cd longQ则使用的方法就?setLong。setXXX Ҏ(gu)的第一个参数是要设|的参数的序C|,W二个参数是讄l该参数的倹{例如,以下代码第一个参数设?123456789Q第二个参数设ؓ 100000000Q?

pstmt.setLong(1, 123456789);
pstmt.setLong(2, 100000000);

一旦设|了l定语句的参数|可用它多次执行该语句,直到调用 clearParameters Ҏ(gu)清除它ؓ止?

在连接的~省模式下(启用自动提交Q,当语句完成时自动提交或q原该语句?

如果基本数据库和驱动E序在语句提交之后仍保持q些语句的打开状态,则同一?PreparedStatement 可执行多ơ。如果这一点不成立Q那么试N过使用 PreparedStatement 对象代替 Statement 对象来提高性能是没有意义的?

利用 pstmtQ前面创建的 PreparedStatement 对象Q,以下代码例示了如何设|两个参数占位符的值ƈ执行 pstmt 10 ơ。如上所qͼ为做到这一点,数据库不能关?pstmt。在该示例中Q第一个参数被讄?"Hi"q保持ؓ常数。在 for 循环中,每次都将W二个参数设|ؓ不同的|?0 开始,?9 l束?

pstmt.setString(1, "Hi");
for (int i = 0; i < 10; i++) {
pstmt.setInt(2, i);
int rowCount = pstmt.executeUpdate();
}

6.1.3 IN 参数中数据类型的一致?
setXXX Ҏ(gu)中的 XXX ?Java cd。它是一U隐含的 JDBC cdQ一?SQL cdQ,因ؓ驱动E序把 Java cd映射为相应的 JDBC cdQ遵循该 JDBC Guide中?.6.2 “映?Java ?JDBC cd”表中所指定的映)Qƈ该 JDBC cd发送给数据库。例如,以下代码D将 PreparedStatement 对象 pstmt 的第二个参数讄?44QJava cd?shortQ?

pstmt.setShort(2, 44);

驱动E序?44 作ؓ JDBC SMALLINT 发送给数据库,它是 Java short cd的标准映?

E序员的责Q是确保将每个 IN 参数?Java cd映射Z数据库所需?JDBC 数据cd兼容?JDBC cd。不妨考虑数据库需?JDBC SMALLINT 的情c如果用方?setByte Q则驱动E序?JDBC TINYINT 发送给数据库。这是可行的Q因多数据库可从一U相关的cd转换为另一U类型,q且通常 TINYINT 可用?SMALLINT 适用的Q何地斏V然而,对于要适用于尽可能多的数据库的应用E序Q最好用与数据库所需的确切的 JDBC cd相应?Java cd。如果所需?JDBC cd?SMALLINTQ则使用 setShort 代替 setByte 应用E序的可UL性更好?


6.1.4 使用 setObject
E序员可使用 setObject Ҏ(gu)昑ּ地将输入参数转换为特定的 JDBC cd。该Ҏ(gu)可以接受W三个参敎ͼ用来指定目标 JDBC cd。将 Java Object 发送给数据库之前,驱动E序把它{换ؓ指定?JDBC cd?

如果没有指定 JDBC cdQ驱动程序就会将 Java Object 映射到其~省?JDBC cdQ参见第 8.6.4 节中的表|Q然后将它发送到数据库。这与常规的 setXXX Ҏ(gu)cMQ在q两U情况下Q驱动程序在值发送到数据库之前,会将该值的 Java cd映射为适当?JDBC cd。二者的差别在于 setXXX Ҏ(gu)使用?Java cd?JDBC cd的标准映(参见W?8.6.2 节中的表|Q?setObject Ҏ(gu)使用?Java Object cd?JDBC cd的映(参见W?8.6.4 节中的表|?

Ҏ(gu) setObject 允许接受所?Java 对象的能力应用E序更ؓ通用Qƈ可在q行时接受参数的输入。这U情况下Q应用程序在~译时ƈ不清楚输入类型。通过使用 setObjectQ应用程序可接受所?Java 对象cd作ؓ输入Qƈ其转换为数据库所需?JDBC cd。第 8.6.5 节中的表格显CZ setObject 可执行的所有可能{换?


6.1.5 ?JDBC NULL 作ؓ IN 参数发?
setNull Ҏ(gu)允许E序员将 JDBC NULL g?IN 参数发送给数据库。但要注意,仍然必须指定参数?JDBC cd?

当把 Java null g递给 setXXX Ҏ(gu)Ӟ如果它接?Java 对象作ؓ参数Q,也将同样?JDBC NULL 发送到数据库。但仅当指定 JDBC cdӞҎ(gu) setObject 才能接受 null 倹{?


6.1.6 发送大?IN 参数
setBytes ?setString Ҏ(gu)能够发送无限量的数据。但是,有时E序员更喜欢用较?yu)的块传递大型的数据。这可通过?IN 参数讄?Java 输入来完成。当语句执行ӞJDBC 驱动E序重复调用该输入,d其内容ƈ它们当作实际参数数据传输?

JDBC 提供了三U将 IN 参数讄入流的方法:setBinaryStream 用于含有未说明字节的, setAsciiStream 用于含有 ASCII 字符的流Q?setUnicodeStream 用于含有 Unicode 字符的流。因为必L定流的总长度,所以这些方法所采用的参数比其它?setXXX Ҏ(gu)要多一个。这很有必要Q因Z些数据库在发送数据之前需要知道其ȝ传送大?

以下代码例示了用流作ؓ IN 参数来发送文件内容: 

java.io.File file = new java.io.File("/tmp/data");
int fileLength = file.length();
java.io.InputStream fin = new java.io.FileInputStream(file);
java.sql.PreparedStatement pstmt = con.prepareStatement(
"UPDATE Table5 SET stuff = ? WHERE index = 4");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();

当语句执行时Q将反复调用输入?fin 以传递其数据?



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630450



風向逆轉 - p爪哇 2006-03-22 03:32 发表评论
]]>
[收藏]JDBCpd教程Q四Q?--l果讄http://www.tkk7.com/iKingQu/articles/36761.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:31:00 GMThttp://www.tkk7.com/iKingQu/articles/36761.htmlhttp://www.tkk7.com/iKingQu/comments/36761.htmlhttp://www.tkk7.com/iKingQu/articles/36761.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36761.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36761.html

JDBCpd教程Q四Q?--l果讄

ResultSet
本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版。?

5.1 概述
ResultSet 包含W合 SQL 语句中条件的所有行Qƈ且它通过一?get Ҏ(gu)Q这?get Ҏ(gu)可以讉K当前行中的不同列Q提供了对这些行中数据的讉K。ResultSet.next Ҏ(gu)用于Ud?ResultSet 中的下一行,使下一行成为当前行?

l果集一般是一个表Q其中有查询所q回的列标题及相应的倹{例如,如果查询?SELECT a, b, c FROM Table1Q则l果集将h如下形式Q?


a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA


下面的代码段是执?SQL 语句的示例。该 SQL 语句返回行集合Q其中列 1 ?intQ列 2 ?StringQ而列 3 则ؓ字节数组Q?


java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// 打印当前行的倹{?
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}

5.1.1 行和光标
ResultSet l护指向其当前数据行的光标。每调用一?next Ҏ(gu)Q光标向下移动一行。最初它位于W一行之前,因此W一ơ调?next 把光标|于W一行上Q它成为当前行。随着每次调用 next D光标向下Ud一行,按照从上至下的次序获?ResultSet 行?

?ResultSet 对象或其父辈 Statement 对象关闭之前Q光标一直保持有效?

?SQL 中,l果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用Ҏ(gu) getCursorName 获得光标名?

注意Q不是所有的 DBMS 都支持定位更新和删除。可使用 DatabaseMetaData.supportsPositionedDelete ?supportsPositionedUpdate Ҏ(gu)来检查特定连接是否支持这些操作。当支持q些操作ӞDBMS/驱动E序必须保适当锁定选定行,以定位更新不会D更新异常或其它ƈ发问题?


5.1.2 ?
Ҏ(gu) getXXX 提供了获取当前行中某列值的途径。在每一行内Q可按Q何次序获取列倹{但Z保证可移植性,应该从左臛_获取列|q且一ơ性地d列倹{?

列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名ؓ“title”,q将值存储ؓ字符Ԍ则下列Q一代码获取存储在该列中的| 

String s = rs.getString("title");
String s = rs.getString(2);

注意列是从左臛_~号的,q且从列 1 开始。同Ӟ用作 getXXX Ҏ(gu)的输入的列名不区分大写?

提供使用列名q个选项的目的是Z让在查询中指定列名的用户可用相同的名字作ؓ getXXX Ҏ(gu)的参数。另一斚wQ如?select 语句未指定列名(例如在“select * from table1”中或列是导出的ӞQ则应该使用列号。这些情况下Q用户将无法切知道列名?

有些情况下,SQL 查询q回的结果集中可能有多个列具有相同的名字。如果列名用?getXXX Ҏ(gu)的参敎ͼ?getXXX 返回第一个匹配列名的倹{因而,如果多个列具有相同的名字Q则需要用列索引来确保检索了正确的列倹{这Ӟ使用列号效率要稍微高一些?

关于 ResultSet 中列的信息,可通过调用Ҏ(gu) ResultSet.getMetaData 得到。返回的 ResultSetMetaData 对象给出其 ResultSet 对象各列的编受类型和属性?

如果列名已知Q但不知其烦引,则可用方?findColumn 得到其列受?


5.1.3 数据cd和{?
对于 getXXX Ҏ(gu)QJDBC 驱动E序试图基本数据{换成指定 Java cdQ然后返回适合?Java 倹{例如,如果 getXXX Ҏ(gu)?getStringQ而基本数据库中数据类型ؓ VARCHARQ则 JDBC 驱动E序把 VARCHAR 转换?Java String。getString 的返回值将?Java String 对象?

下表昄了允许用 getXXX 获取?JDBC cd及推荐用它获取的 JDBC cdQ通用 SQL cdQ。小写的 x 表示允许 getXXX Ҏ(gu)获取该数据类型;大写?X 表示对该数据cd推荐使用 getXXX Ҏ(gu)。例如,除了 getBytes ?getBinaryStream 之外的Q?getXXX Ҏ(gu)都可用来获取 LONGVARCHAR |但是推荐Ҏ(gu)q回的数据类型?getAsciiStream ?getUnicodeStream Ҏ(gu)。方?getObject Q何数据类型返回ؓ Java Object。当基本数据cd是特定于数据库的抽象cd或当通用应用E序需要接受Q何数据类型时Q它是非常有用的?

可?ResultSet.getXXX Ҏ(gu)获取常见?JDBC 数据cd?

“x”表C getXXX Ҏ(gu)可合法地用于获取l定 JDBC cd?

“X”表C推荐用该 getXXX Ҏ(gu)来获取给?JDBC cd?

  T
I
N
Y
I
N
T S
M
A
L
L
I
N
T I
N
T
E
G
E
R B
I
G

N
T R
E
A
L F
L
O
A
T D
O
U
B
L
E D
E
C
I
M
A
L N
U
M
E
R
I
C B
I
T C
H
A
R V
A
R
C
H
A
R
L
O
N
G
V
A
R
C
H
A
R B
I
N
A
R
Y V
A
R
B
I
N
A
R
Y L
O
N
G
V
A
R
B
I
N
A
R
Y D
A
T
E T
I
M
E T
I
M
E
S
T
A
M

getByte X x x x x x x x x x x x x             
getShort x X x x x x x x x x x x x             
getInt x x X x x x x x x x x x x             
getLong x x x X x x x x x x x x x             
getFloat x x x x X x x x x x x x x             
getDouble x x x x x X X x x x x x x             
getBigDecimal x x x x x x x X X x x x x             
getBoolean x x x x x x x x x X x x x             
getString x x x x x x x x x x X X x x x x x x x 
getBytes                           X X x       
getDate                     x x x       X   x 
getTime                     x x x         X x 
getTimestamp                     x x x       x   X 
getAsciiStream                     x x X x x x       
getUnicodeStream                     x x X x x x       
getBinaryStream                           x x X       
getObject x x x x x x x x x x x x x x x x x x x 


5.1.4 寚w常大的行g用流
ResultSet 可以获取L大的 LONGVARBINARY ?LONGVARCHAR 数据。方?getBytes ?getString 数据返回ؓ大的块(最大ؓ Statement.getMaxFieldSize 的返回|。但是,以较?yu)的固定块获取非常大的数据可能会更方便,而这可通过?ResultSet c返?java.io.Input 来完成。从该流中可分块d数据。注意:必须立即讉Kq些,因ؓ在下一ơ对 ResultSet 调用 getXXX 时它们将自动关闭Q这是由于基本实现对大块数据讉K有限Ӟ。?

JDBC API h三个获取的Ҏ(gu)Q分别具有不同的q回| 


getBinaryStream q回只提供数据库原字节而不q行M转换的流?


getAsciiStream q回提供单字?ASCII 字符的流?


getUnicodeStream q回提供双字?Unicode 字符的流?


注意Q它不同?Java ,后者返回无cd字节q可Q例如)通用?ASCII ?Unicode 字符?

下列代码演示?getAsciiStream 的用法: 

java.sql.Statement stmt = con.createStatement();
ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
// 现在?4K 块大获取列 1 l果Q?
byte buff = new byte[4096];
while (r.next()) {
Java.io.InputStream fin = r.getAsciiStream(1);
for (;;) {
int size = fin.read(buff);
if (size == -1) { // 到达末?
break;
}
// 新填充的缓冲区发送到 ASCII 输出:
output.write(buff, 0, size);
}
}

5.1.5 NULL l果?
要确定给定结果值是否是 JDBC NULLQ必dd该列Q然后?ResultSet.wasNull Ҏ(gu)查该ơ读取是否返?JDBC NULL?

当?ResultSet.getXXX Ҏ(gu)d JDBC NULL ӞҎ(gu) wasNull 返回下列g一Q?


Java null |对于q回 Java 对象?getXXX Ҏ(gu)Q例?getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject {)?


零|对于 getByte、getShort、getInt、getLong、getFloat ?getDouble?


false |对于 getBoolean?


5.1.6 可选结果集或多l果?
通常使用 executeQueryQ它q回单个 ResultSetQ或 executeUpdateQ它可用于Q何数据库修改语句Qƈq回更新行数Q可执行 SQL 语句。但有些情况下,应用E序在执行语句之前不知道该语句是否返回结果集。此外,有些已存储过E可能返回几个不同的l果集和/或更新计数?

Z适应q些情况QJDBC 提供了一U机Ӟ允许应用E序执行语句Q然后处理由l果集和更新计数l成的Q意集合。这U机制的原理是首先调用一个完全通用?execute Ҏ(gu)Q然后调用另外三个方法,getResultSet、getUpdateCount ?getMoreResults。这些方法允许应用程序一ơ一个地研究语句l果Qƈ定l定l果?ResultSet q是更新计数?

用户不必关闭 ResultSetQ当产生它的 Statement 关闭、重新执行或用于从多l果序列中获取下一个结果时Q该 ResultSet 被 Statement 自动关闭。?



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630447



風向逆轉 - p爪哇 2006-03-22 03:31 发表评论
]]>
[收藏]JDBCpd教程Q三Q?--语句http://www.tkk7.com/iKingQu/articles/36760.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:30:00 GMThttp://www.tkk7.com/iKingQu/articles/36760.htmlhttp://www.tkk7.com/iKingQu/comments/36760.htmlhttp://www.tkk7.com/iKingQu/articles/36760.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36760.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36760.html

JDBCpd教程Q三Q?--语句

Statement
本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版。?

4.1 概述
Statement 对象用于?SQL 语句发送到数据库中。实际上有三U?Statement 对象Q它们都作ؓ在给定连接上执行 SQL 语句的包容器QStatement、PreparedStatementQ它?Statement l承而来Q和 CallableStatementQ它?PreparedStatement l承而来Q。它们都专用于发送特定类型的 SQL 语句Q?Statement 对象用于执行不带参数的简?SQL 语句QPreparedStatement 对象用于执行带或不带 IN 参数的预~译 SQL 语句QCallableStatement 对象用于执行Ҏ(gu)据库已存储过E的调用?

Statement 接口提供了执行语句和获取l果的基本方法。PreparedStatement 接口d了处?IN 参数的方法;?CallableStatement d了处?OUT 参数的方法?


4.1.1 创徏 Statement 对象
建立了到特定数据库的q接之后Q就可用该连接发?SQL 语句。Statement 对象?Connection 的方?createStatement 创徏Q如下列代码D中所C: 

Connection con = DriverManager.getConnection(url, "sunny", "");
Statement stmt = con.createStatement();

Z执行 Statement 对象Q被发送到数据库的 SQL 语句被作ؓ参数提供l?Statement 的方法: 

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2");

4.1.2 使用 Statement 对象执行语句
Statement 接口提供了三U执?SQL 语句的方法:executeQuery、executeUpdate ?execute。用哪一个方法由 SQL 语句所产生的内容决定?

Ҏ(gu) executeQuery 用于产生单个l果集的语句Q例?SELECT 语句?

Ҏ(gu) executeUpdate 用于执行 INSERT、UPDATE ?DELETE 语句以及 SQL DDLQ数据定义语aQ语句,例如 CREATE TABLE ?DROP TABLE。INSERT、UPDATE ?DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整敎ͼ指示受媄响的行数Q即更新计数Q。对?CREATE TABLE ?DROP TABLE {不操作行的语句QexecuteUpdate 的返回值Mؓ零?

Ҏ(gu) execute 用于执行q回多个l果集、多个更新计数或二者组合的语句。因为多数程序员不会需要该高功能Q所以本概述后面在单独一节中对其q行介绍?

执行语句的所有方法都关闭所调用?Statement 对象的当前打开l果集(如果存在Q。这意味着在重新执?Statement 对象之前Q需要完成对当前 ResultSet 对象的处理?

应注意,l承?Statement 接口中所有方法的 PreparedStatement 接口都有自己?executeQuery、executeUpdate ?execute Ҏ(gu)。Statement 对象本n不包?SQL 语句Q因而必ȝ Statement.execute Ҏ(gu)提供 SQL 语句作ؓ参数。PreparedStatement 对象q不?SQL 语句作ؓ参数提供l这些方法,因ؓ它们已经包含预编?SQL 语句。CallableStatement 对象l承q些Ҏ(gu)?PreparedStatement 形式。对于这些方法的 PreparedStatement ?CallableStatement 版本Q用查询参数将抛出 SQLException?


4.1.3 语句完成
当连接处于自动提交模式时Q其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有结果返回时Q即认ؓ已完成。对于返回一个结果集?executeQuery Ҏ(gu)Q在索完 ResultSet 对象的所有行时该语句完成。对于方?executeUpdateQ当它执行时语句卛_成。但在少数调用方?execute 的情况中Q在索所有结果集或它生成的更新计C后语句才完成?

有些 DBMS 已存储q程中的每条语句视ؓ独立的语句;而另外一些则整个过E视Z个复合语句。在启用自动提交Ӟq种差别变得非帔R要,因ؓ它媄响什么时候调?commit Ҏ(gu)。在前一U情况中Q每条语句单独提交;在后一U情况中Q所有语句同时提交?


4.1.4 关闭 Statement 对象
Statement 对象由 Java 垃圾攉E序自动关闭。而作ZU好的编E风|应在不需?Statement 对象时显式地关闭它们。这立即释?DBMS 资源Q有助于避免潜在的内存问题?


4.1.5 Statement 对象中的 SQL 转义语法 
Statement 可包含?SQL 转义语法?SQL 语句。{义语法告诉驱动程序其中的代码应该以不同方式处理。驱动程序将扫描M转义语法Qƈ它转换成特定数据库可理解的代码。这使得转义语法?DBMS 无关Qƈ允许E序员用在没有转义语法时不可用的功能?

转义子句p括号和关键字界定Q?

{keyword . . . parameters . . . }

该关键字指示转义子句的类型,如下所C?


escape 表示 LIKE 转义字符 


字符?”和“_”类g SQL LIKE 子句中的通配W(?”匹配零个或多个字符Q而“_”则匚w一个字W)。ؓ了正解释它们,应在其前面加上反斜杠Q“\”)Q它是字W串中的Ҏ(gu)转义字符。在查询末尾包括如下语法卛_指定用作转义字符的字W: 

{escape 'escape-character'}


例如Q下列查询用反斜杠字符作ؓ转义字符Q查找以下划U开头的标识W名Q?

stmt.executeQuery("SELECT name FROM Identifiers
WHERE Id LIKE `\_%' {escape `\'};


fn 表示标量函数


几乎所?DBMS 都具有标量值的数倹{字W串、时间、日期、系l和转换函数。要使用q些函数Q可使用如下转义语法Q关键字 fn 后跟所需的函数名及其参数。例如,下列代码调用函数 concat 两个参数连接在一P 

{fn concat("Hot", "Java")};


可用下列语法获得当前数据库用户名Q?

{fn user()};


标量函数可能p法稍有不同的 DBMS 支持Q而它们可能不被所有驱动程序支持。各U?DatabaseMetaData Ҏ(gu)列出所支持的函数。例如,Ҏ(gu) getNumericFunctions q回用逗号分隔的数值函数列表,而方?getStringFunctions 返回字W串函数Q等{?

驱动E序{义函数调用映ؓ相应的语法,或直接实现该函数?


d、t ?ts 表示日期和时间文?


DBMS 用于日期、时间和旉标记文字的语法各不相同。JDBC 使用转义子句支持q些文字的语法的 ISO 标准格式。驱动程序必d转义子句转换?DBMS 表示?

例如Q可用下列语法在 JDBC SQL 语句中指定日期: 

{d `yyyy-mm-dd'}


在该语法中,yyyy 为年代,mm 为月份,?dd 则ؓ日期。驱动程序将用等L特定?DBMS 的表C替换这个{义子句。例如,如果 '28- FEB-99' W合基本数据库的格式Q则驱动E序用它替?{d 1999-02-28}?

对于 TIME ?TIMESTAMP 也有cM的{义子句: 

{t `hh:mm:ss'}
{ts `yyyy-mm-dd hh:mm:ss.f . . .'}


TIMESTAMP 中的数点后的秒Q?f . . .Q部分可忽略?


call ?? = call 表示已存储过E?


如果数据库支持已存储q程Q则可从 JDBC 中调用它们,语法为: 

{call procedure_name[(?, ?, . . .)]}


或(其中q程q回l果参数Q: 

{? = call procedure_name[(?, ?, . . .)]}


Ҏ(gu)hC其中的内容是可选的。它们不是语法的必要部分?

输入参数可以为文字或参数。有兌l信息,参见 JDBC 指南中第 7 节,“CallableStatement”?

可通过调用Ҏ(gu) DatabaseMetaData.supportsStoredProcedures 查数据库是否支持已存储过E?


oj 表示外部q接


外部q接的语法ؓ 

{oj outer-join}


其中 outer-join 形式为?

table LEFT OUTER JOIN {table / outer-join} ON search-condition


外部q接属于高功能。有兛_们的解释可参?SQL 语法。JDBC 提供了三U?DatabaseMetaData Ҏ(gu)用于定驱动E序支持哪些外部q接cdQsupportsOuterJoins、supportsFullOuterJoins ?supportsLimitedOuterJoins?


Ҏ(gu) Statement.setEscapeProcessing 可打开或关闭{义处理;~省状态ؓ打开。当性能极ؓ重要ӞE序员可能想关闭它以减少处理旉。但通常它将Z打开状态。应注意Q?setEscapeProcessing 不适用?PreparedStatement 对象Q因为在调用该语句前它就可能已被发送到数据库。有关预~译的信息,参见 PreparedStatement?


4.1.6 使用Ҏ(gu) execute
execute Ҏ(gu)应该仅在语句能返回多?ResultSet 对象、多个更新计数或 ResultSet 对象与更新计数的l合时用。当执行某个已存储过E或动态执行未?SQL 字符Ԍ卛_用程序程序员在编译时未知Q时Q有可能出现多个l果的情况,管q种情况很少见。例如,用户可能执行一个已存储q程Q?CallableStatement 对象 - 参见W?135 늚 CallableStatementQ,q且该已存储q程可执行更斎ͼ然后执行选择Q再q行更新Q再q行选择Q等{。通常使用已存储过E的人应知道它所q回的内宏V?

因ؓҎ(gu) execute 处理非常规情况,所以获取其l果需要一些特D处理ƈ不为怪。例如,假定已知某个q程q回两个l果集,则在使用Ҏ(gu) execute 执行该过E后Q必调用方?getResultSet 获得W一个结果集Q然后调用适当?getXXX Ҏ(gu)获取其中的倹{要获得W二个结果集Q需要先调用 getMoreResults Ҏ(gu)Q然后再调用 getResultSet Ҏ(gu)。如果已知某个过E返回两个更新计敎ͼ则首先调用方?getUpdateCountQ然后调?getMoreResultsQƈ再次调用 getUpdateCount?

对于不知道返回内容,则情冉|为复杂。如果结果是 ResultSet 对象Q则Ҏ(gu) execute q回 trueQ如果结果是 Java intQ则q回 false。如果返?intQ则意味着l果是更新计数或执行的语句是 DDL 命o。在调用Ҏ(gu) execute 之后要做的第一件事情是调用 getResultSet ?getUpdateCount。调用方?getResultSet 可以获得两个或多?ResultSet 对象中第一个对象;或调用方?getUpdateCount 可以获得两个或多个更新计CW一个更新计数的内容?

?SQL 语句的结果不是结果集Ӟ则方?getResultSet 返?null。这可能意味着l果是一个更新计数或没有其它l果。在q种情况下,判断 null 真正含义的唯一Ҏ(gu)是调用方?getUpdateCountQ它?yu)返回一个整数。这个整Cؓ调用语句所影响的行敎ͼ如果?-1 则表C结果是l果集或没有l果。如果方?getResultSet 已返?nullQ表C结果不?ResultSet 对象Q,则返回?-1 表示没有其它l果。也是_当下列条件ؓ真时表示没有l果Q或没有其它l果Q: 

((stmt.getResultSet() == null) && (stmt.getUpdateCount() == -1))

如果已经调用Ҏ(gu) getResultSet q处理了它返回的 ResultSet 对象Q则有必要调用方?getMoreResults 以确定是否有其它l果集或更新计数。如?getMoreResults q回 trueQ则需要再ơ调?getResultSet 来检索下一个结果集。如上所qͼ如果 getResultSet q回 nullQ则需要调?getUpdateCount 来检?null 是表C结果ؓ更新计数q是表示没有其它l果?

?getMoreResults q回 false Ӟ它表C SQL 语句q回一个更新计数或没有其它l果。因此需要调用方?getUpdateCount 来检查它是哪一U情c在q种情况下,当下列条件ؓ真时表示没有其它l果Q?

((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))

下面的代码演CZ一U方法用来确认已讉K调用Ҏ(gu) execute 所产生的全部结果集和更新计敎ͼ 


stmt.execute(queryStringWithUnknownResults);
while (true) {
int rowCount = stmt.getUpdateCount();
if (rowCount > 0) { // 它是更新计数
System.out.println("Rows changed = " + count);
stmt.getMoreResults();
continue;
}
if (rowCount == 0) { // DDL 命o?0 个更?
System.out.println(" No rows changed or statement was DDL
command");
stmt.getMoreResults();
continue;
}

// 执行到这里,证明有一个结果集
// 或没有其它结?

ResultSet rs = stmt.getResultSet;
if (rs != null) {
. . . // 使用元数据获得关于结果集列的信息
while (rs.next()) {
. . . // 处理l果
stmt.getMoreResults();
continue;
}
break; // 没有其它l果



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630445



風向逆轉 - p爪哇 2006-03-22 03:30 发表评论
]]>
[收藏]JDBCpd教程Q二Q?--驱动讄http://www.tkk7.com/iKingQu/articles/36759.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:28:00 GMThttp://www.tkk7.com/iKingQu/articles/36759.htmlhttp://www.tkk7.com/iKingQu/comments/36759.htmlhttp://www.tkk7.com/iKingQu/articles/36759.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36759.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36759.html

JDBCpd教程Q二Q?--驱动讄

DriverManager
本概q摘自《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference》,目前正由 JavaSoft l箋~写。这本书既是 JDBC 的教E,也是一本权威性参考手册,作?Java pd的一部分?1997 q春季由 Addison-Wesley 出版公司出版。?

3.1 概述
DriverManager cL JDBC 的管理层Q作用于用户和驱动程序之间。它跟踪可用的驱动程序,q在数据库和相应驱动E序之间建立q接。另外,DriverManager cM处理诸如驱动E序d旉限制及登录和跟踪消息的显C等事务?

对于单的应用E序Q一般程序员需要在此类中直接用的唯一Ҏ(gu)?DriverManager.getConnection。正如名U所C,该方法将建立与数据库的连接。JDBC 允许用户调用 DriverManager 的方?getDriver、getDrivers ?registerDriver ?Driver 的方?connect。但多数情况下,?DriverManager cȝ理徏立连接的l节Z{?


3.1.1 跟踪可用驱动E序
DriverManager cd含一?Driver c,它们已通过调用Ҏ(gu) DriverManager.registerDriver 对自p行了注册。所?Driver c都必须包含有一个静态部分。它创徏该类的实例,然后在加载该实例?DriverManager c进行注册。这P用户正常情况下将不会直接调用 DriverManager.registerDriverQ而是在加载驱动程序时由驱动程序自动调用。加?Driver c,然后自动?DriverManager 中注册的方式有两U: 


通过调用Ҏ(gu) Class.forName。这显式地加蝲驱动E序cR由于这与外部设|无养I因此推荐使用q种加蝲驱动E序的方法。以下代码加载类 acme.db.DriverQ?
Class.forName("acme.db.Driver");

如果?acme.db.Driver ~写为加载时创徏实例Qƈ调用以该实例为参数的 DriverManager.registerDriverQ本该如此)Q则它在 DriverManager 的驱动程序列表中Qƈ可用于创接?


通过驱动程序添加到 java.lang.System 的属?jdbc.drivers 中。这是一个由 DriverManager cd载的驱动E序cd的列表,由冒号分隔:初始?DriverManager cLQ它搜烦pȝ属?jdbc.driversQ如果用户已输入了一个或多个驱动E序Q则 DriverManager cd试图加蝲它们。以下代码说明程序员如何?~/.hotjava/properties 中输入三个驱动程序类Q启动时QHotJava 把它加载到pȝ属性列表中Q: 
jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver;

?DriverManager Ҏ(gu)的第一ơ调用将自动加蝲q些驱动E序cR?

注意Q加载驱动程序的W二U方法需要持久的预设环境。如果对q一点不能保证,则调用方?Class.forName 昑ּ地加载每个驱动程序就昑־更ؓ安全。这也是引入特定驱动E序的方法,因ؓ一?DriverManager c被初始化,它将不再?jdbc.drivers 属性列表?

在以上两U情况中Q新加蝲?Driver c都要通过调用 DriverManager.registerDriver c进行自我注册。如上所qͼ加蝲cL自动执行这一q程?

׃安全斚w的原因,JDBC 理层将跟踪哪个cd载器提供哪个驱动E序。这P?DriverManager cL开q接Ӟ它仅使用本地文gpȝ或与发出q接h的代码相同的cd载器提供的驱动程序?


3.1.2 建立q接
加蝲 Driver cdƈ?DriverManager cM注册后,它们卛_用来与数据库建立q接。当调用 DriverManager.getConnection Ҏ(gu)发出q接hӞDriverManager 检查每个驱动程序,查看它是否可以徏立连接?

有时可能有多?JDBC 驱动E序可以与给定的 URL q接。例如,与给定远E数据库q接Ӟ可以使用 JDBC-ODBC 桥驱动程序、JDBC 到通用|络协议驱动E序或数据库厂商提供的驱动程序。在q种情况下,试驱动E序的顺序至关重要,因ؓ DriverManager 用它所扑ֈ的第一个可以成功连接到l定 URL 的驱动程序?

首先 DriverManager 试图按注册的序使用每个驱动E序Qjdbc.drivers 中列出的驱动E序L先注册)。它?yu)蟩q代码不可信ȝ驱动E序Q除非加载它们的源与试图打开q接的代码的源相同?

它通过轮流在每个驱动程序上调用Ҏ(gu) Driver.connectQƈ向它们传递用户开始传递给Ҏ(gu) DriverManager.getConnection ?URL 来对驱动E序q行试Q然后连接第一个认 URL 的驱动程序?

q种Ҏ(gu)初看h效率不高Q但׃不可能同时加载数十个驱动E序Q因此每ơ连接实际只需几个q程调用和字W串比较?

以下代码是通常情况下用驱动E序Q例?JDBC-ODBC 桥驱动程序)建立q接所需所有步骤的CZQ?

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加蝲驱动E序
String url = "jdbc:odbc:fred";
DriverManager.getConnection(url, "userID", "passwd");



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630442



風向逆轉 - p爪哇 2006-03-22 03:28 发表评论
]]>
[收藏]JDBCpd教程Q一Q?--q接http://www.tkk7.com/iKingQu/articles/36758.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:27:00 GMThttp://www.tkk7.com/iKingQu/articles/36758.htmlhttp://www.tkk7.com/iKingQu/comments/36758.htmlhttp://www.tkk7.com/iKingQu/articles/36758.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36758.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36758.html

JDBCpd教程Q一Q?--q接

q接
本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这本书是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版。?


2.1 概述
Connection 对象代表与数据库的连接。连接过E包括所执行?SQL 语句和在该连接上所q回的结果。一个应用程序可与单个数据库有一个或多个q接Q或者可与许多数据库有连接?


2.1.1 打开q接
与数据库建立q接的标准方法是调用 DriverManager.getConnection Ҏ(gu)。该Ҏ(gu)接受含有某个 URL 的字W串。DriverManager c(x谓的 JDBC 理层)尝试找到可与那?URL 所代表的数据库q行q接的驱动程序。DriverManager cd有已注册?Driver cȝ清单。当调用Ҏ(gu) getConnection Ӟ它将查清单中的每个驱动程序,直到扑ֈ可与 URL 中指定的数据库进行连接的驱动E序为止。Driver 的方?connect 使用q个 URL 来徏立实际的q接?

用户可绕q?JDBC 理层直接调?Driver Ҏ(gu)。这在以下特D情况下很有用Q当两个驱动器可同时q接到数据库中,而用户需要明地选用其中特定的驱动器。但一般情况下Q让 DriverManager cd理打开q接q种事将更ؓ单?

下述代码昄如何打开一个与位于 URL "jdbc:odbc:wombat" 的数据库的连接。所用的用户标识Wؓ "oboy" Q口令ؓ "12Java"Q?

String url = "jdbc:odbc:wombat";
Connection con = DriverManager.getConnection(url, "oboy", "12Java");

2.1.2 一般用法的 URL
׃ URL 常引h؜淆,我们先对一?URL 作简单说明,然后再讨?JDBC URL?

URLQ统一资源定位W)提供?Internet 上定位资源所需的信息。可它惌Z个地址?

URL 的第一部䆾指定了访问信息所用的协议Q后面L跟着冒号。常用的协议?"ftp"Q代表“文件传输协议”)?"http" Q代表“超文本传输协议”)。如果协议是 "file"Q表C源是在某个本地文件系l上而非?Internet 上(下例用于表示我们所描述的部分;它ƈ?URL 的组成部分)?

ftp://javasoft.com/docs/JDK-1_apidocs.zip
http://java.sun.com/products/jdk/CurrentRelease
file:/home/haroldw/docs/books/tutorial/summary.html

URL 的其余部份(冒号后面的)l出了数据资源所处位|的有关信息。如果协议是 fileQ则 URL 的其余部份是文g的\径。对?ftp ?http 协议QURL 的其余部份标识了Lq可选地l出某个更详的地址路径。例如,以下?JavaSoft 主页?URL。该 URL 只标识了LQ?

http://java.sun.com

从该主页开始浏览,可以进到许多其它的|页中,其中之一是 JDBC 主页。JDBC 主页?URL 更ؓ具体Q它看v来类| 

http://java.sun.com/products/jdbc

2.1.3 JDBC URL 
JDBC URL 提供了一U标识数据库的方法,可以使相应的驱动E序能识别该数据库ƈ与之建立q接。实际上Q驱动程序编E员决定用什?JDBC URL 来标识特定的驱动E序。用户不必关心如何来形成 JDBC URLQ他们只M用与所用的驱动E序一h供的 URL 卛_。JDBC 的作用是提供某些U定Q驱动程序编E员在构造他们的 JDBC URL 时应该遵循这些约定?

׃ JDBC URL 要与各种不同的驱动程序一起用,因此q些U定应非常灵zR首先,它们应允怸同的驱动E序使用不同的方案来命名数据库。例如, odbc 子协议允许(但ƈ不是要求Q?URL 含有属性倹{?

W二QJDBC URL 应允讔R动程序编E员一切所需的信息编入其中。这样就可以让要与给定数据库对话?applet 打开数据库连接,而无要求用户去做Q何系l管理工作?

W三Q?JDBC URL 应允许某U程度的间接性。也是_JDBC URL 可指向逻辑L或数据库名,而这U逻辑L或数据库名将ql命名系l动态地转换为实际的名称。这可以使系l管理员不必特定主机声明ؓ JDBC 名称的一部䆾。网l命名服务(例如 DNS?NIS ?DCE Q有多种,而对于用哪U命名服务ƈ无限制?

JDBC URL 的标准语法如下所C。它׃部分l成Q各部分间用冒号分隔Q?

jdbc:< 子协?>:< 子名U?>

JDBC URL 的三个部分可分解如下Q?


jdbc ─ 协议。JDBC URL 中的协议L jdbc?


<子协?gt; ─ 驱动E序名或数据库连接机Ӟq种机制可由一个或多个驱动E序支持Q的名称。子协议名的典型CZ?"odbc"Q该名称是ؓ用于指定 ODBC 风格的数据资源名U的 URL 专门保留的。例如,Z通过 JDBC-ODBC 桥来讉K某个数据库,可以用如下所C的 URLQ?
jdbc:odbc:fred

本例中,子协议ؓ "odbc"Q子名称 "fred" 是本?
ODBC 数据资源?

如果要用|络命名服务Q这?JDBC URL 中的数据库名UC必是实际名称Q,则命名服务可以作为子协议。例如,可用如下所C的 URL Q?

jdbc:dcenaming:accounts-payable

本例中,?URL 指定了本?DCE 命名服务应该?
数据库名U?"accounts-payable" 解析为更为具体的
可用于连接真实数据库的名U?


<子名U?gt; ─ 一U标识数据库的方法。子名称可以依不同的子协议而变化。它q可以有子名U的子名Uͼ含有驱动E序~程员所选的M内部语法Q。用子名称的目的是为定位数据库提供_的信息。前例中Q因?ODBC 提供其余部份的信息Q因此用 "fred" 已_。然而,位于q程服务器上的数据库需要更多的信息。例如,如果数据库是通过 Internet 来访问的Q则?JDBC URL 中应网l地址作ؓ子名U的一部䆾包括q去Q且必须遵@如下所C的标准 URL 命名U定Q?
//L?端口/子协?

假设 "dbnet" 是个用于某个主接到 Internet 上的协议Q则 JDBC URL cMQ?

jdbc:dbnet://wombat:356/fred 

2.1.4 "odbc" 子协?
子协?odbc 是一U特D情c它是ؓ用于指定 ODBC 风格的数据资源名U的 URL 而保留的Qƈh下列Ҏ(gu):允许在子名称Q数据资源名Uͼ后面指定L多个属性倹{odbc 子协议的完整语法为: 


jdbc:odbc:< 数据资源名称 >[;< 属性名 >=< 属性?>]*

因此Q以下都是合法的 jdbc:odbc 名称Q?

jdbc:odbc:qeor7
jdbc:odbc:wombat
jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
jdbc:odbc:qeora;UID=kgh;PWD=fooey

2.1.5 注册子协?
驱动E序~程员可保留某个名称以将之用?JDBC URL 的子协议名。当 DriverManager cd此名U加到已注册的驱动程序清单中ӞZ保留该名U的驱动E序应能识别该名Uƈ与它所标识的数据库建立q接。例如,odbc 是ؓ JDBC- ODBC 桥而保留的。示例之二,假设有个 Miracle 公司Q它可能会将 "miracle" 注册接到?Miracle DBMS 上的 JDBC 驱动E序的子协议Q从而其他人都无法使用q个名称?

JavaSoft 目前作ؓ非正式代理负责注?JDBC 子协议名U。要注册某个子协议名Uͼ请发送电(sh)子邮件到下述地址Q?

jdbc@wombat.eng.sun.com

2.1.6 发?SQL 语句
q接一旦徏立,可用来向它所涉及的数据库传?SQL 语句。JDBC 对可被发送的 SQL 语句cd不加M限制。这提供了很大的灵zL,卛_怋用特定的数据库语句或甚至于非 SQL 语句。然而,它要求用戯p责确保所涉及的数据库可以处理所发送的 SQL 语句Q否则将自食其果。例如,如果某个应用E序试图向不支持储存E序?DBMS 发送储存程序调用,׃p|q将抛出异常。JDBC 要求驱动E序应至能提供 ANSI SQL-2 Entry Level 功能才可是W合 JDBC 标准TM 的。这意味着用户臛_可信赖这一标准U别的功能?

JDBC 提供了三个类Q用于向数据库发?SQL 语句。Connection 接口中的三个Ҏ(gu)可用于创些类的实例。下面列些类及其创徏Ҏ(gu)Q?


Statement ─ 由方?createStatement 所创徏。Statement 对象用于发送简单的 SQL 语句。?
PreparedStatement ─ 由方?prepareStatement 所创徏。PreparedStatement 对象用于发送带有一个或多个输入参数Q?IN 参数Q的 SQL 语句。PreparedStatement 拥有一l方法,用于讄 IN 参数的倹{执行语句时Q这?IN 参数被送到数据库中。PreparedStatement 的实例扩展了 Statement Q因此它们都包括?Statement 的方法。PreparedStatement 对象有可能比 Statement 对象的效率更高,因ؓ它已被预~译qƈ存放在那以供来使用。?
CallableStatement ─ 由方?prepareCall 所创徏。CallableStatement 对象用于执行 SQL 储存E序 ─ 一l可通过名称来调用(p函数的调用那P?SQL 语句。CallableStatement 对象?PreparedStatement 中承了用于处理 IN 参数的方法,而且q增加了用于处理 OUT 参数?INOUT 参数的方法。?

以下所列提供的Ҏ(gu)可以快速决定应用哪?Connection Ҏ(gu)来创Z同类型的 SQL 语句Q?


createStatement Ҏ(gu)用于Q?


单的 SQL 语句Q不带参敎ͼ 


prepareStatement Ҏ(gu)用于Q?


带一个或多个 IN 参数?SQL 语句 


l常被执行的?SQL 语句


prepareCall Ҏ(gu)用于Q?


调用已储存过E?


2.1.7 事务
事务׃个或多个q样的语句组成:q些语句已被执行、完成ƈ被提交或q原。当调用Ҏ(gu) commit ?rollback Ӟ当前事务卛_q束,另一个事务随卛_始?

~省情况下,新连接将处于自动提交模式。也是_当执行完语句后,自动对那个语句调用 commit Ҏ(gu)。这U情况下Q由于每个语句都是被单独提交的,因此一个事务只׃个语句组成。如果禁用自动提交模式,事务要{到 commit ?rollback Ҏ(gu)被显式调用时才结束,因此它将包括上一ơ调?commit ?rollback Ҏ(gu)以来所有执行过的语句。对于第二种情况Q事务中的所有语句将作ؓl来提交或还原?

Ҏ(gu) commit ?SQL 语句Ҏ(gu)据库所做的M更改成ؓ怹性的Q它q将释放事务持有的全部锁。而方?rollback 弃去那些更攏V?

有时用户在另一个更改生效前不想让此更改生效。这可通过用自动提交q将两个更新l合在一个事务中来达到。如果两个更新都是成功的Q则调用 commit Ҏ(gu)Q从而两个更新l果成ؓ怹性的Q如果其中之一或两个更新都p|了,则调?rollback Ҏ(gu)Q以值恢复ؓq行更新之前的倹{?

大多?JDBC 驱动E序都支持事务。事实上Q符?JDBC 的驱动程序必L持事务。DatabaseMetaData l出的信息描q?DBMS 所提供的事务支持水q?


2.1.8 事务隔离U别
如果 DBMS 支持事务处理Q它必须有某U途径来管理两个事务同时对一个数据库q行操作时可能发生的冲突。用户可指定事务隔离U别Q以指明 DBMS 应该花多大精力来解决潜在冲突。例如,当事务更改了某个D第二个事务却在该更改被提交或还原前d该值时该怎么办? 假设W一个事务被q原后,W二个事务所d的更改值将是无效的Q那么是否可允许q种冲突Q?JDBC 用户可用以下代码来指C?DBMS 允许在D提交前读取该|“dirty d”)Q其?con 是当前连接: 

con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

事务隔离U别高Qؓ避免冲突所q_֊也就多。Connection 接口定义了五U,其中最低别指定了Ҏ(gu)׃支持事务Q而最高别则指定当事务在Ҏ(gu)个数据库q行操作ӞM其它事务不得寚w个事务正在读取的数据q行M更改。通常Q隔ȝ别越高,应用E序执行的速度也就慢Q由于用于锁定的资源耗费增加了,而用户间的ƈ发操作减了Q。在军_采用什么隔ȝ别时Q开发h员必d性能需求和数据一致性需求之间进行权衡。当Ӟ实际所能支持的U别取决于所涉及?DBMS 的功能?

当创?Connection 对象Ӟ其事务隔ȝ别取决于驱动E序Q但通常是所涉及的数据库的缺省倹{用户可通过调用 setIsolationLevel Ҏ(gu)来更改事务隔ȝ别。新的别将在该q接q程的剩余时间内生效。要惛_改变一个事务的事务隔离U别Q必d该事务开始前q行讄Qƈ在该事务l束后进行复位。我们不提倡在事务的中途对事务隔离U别q行更改Q因立卌?commit Ҏ(gu)的调用,使在此之前所作的M更改变成怹性的。?



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=630439



風向逆轉 - p爪哇 2006-03-22 03:27 发表评论
]]>
[收藏]JavaE序员的存储q程http://www.tkk7.com/iKingQu/articles/36757.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 21 Mar 2006 19:26:00 GMThttp://www.tkk7.com/iKingQu/articles/36757.htmlhttp://www.tkk7.com/iKingQu/comments/36757.htmlhttp://www.tkk7.com/iKingQu/articles/36757.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36757.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36757.html

JavaE序员的存储q程
--------------------------------------------------------------------------------

原文Q?a >http://www.onjava.com/pub/a/onjava/2003/08/13/stored_procedures.html
by Nic Ferrier

本文阐述了怎么使用DBMS存储q程。我阐述了用存储过E的基本的和高Ҏ(gu),比如q回ResultSet。本文假设你对DBMS和JDBC已经非常熟?zhn)Q也假设你能够毫无障地阅读其它语言写成的代码(即不是Java的语aQ,但是Qƈ不要求你有Q何存储过E的~程l历?
存储q程是指保存在数据库q在数据库端执行的程序。你可以使用Ҏ(gu)的语法在JavacM调用存储q程。在调用Ӟ存储q程的名U及指定的参数通过JDBCq接发送给DBMSQ执行存储过Eƈ通过q接Q如果有Q返回结果?
使用存储q程拥有和用基于EJB或CORBAq样的应用服务器一L好处。区别是存储q程可以从很多流行的DBMS中免费用,而应用服务器大都非常昂贵。这q不只是许可证费用的问题。用应用服务器所需要花费的理、编写代码的费用Q以及客L序所增加的复杂性,都可以通过DBMS中的存储q程所整个地替代?
你可以用JavaQPythonQPerl或C~写存储q程Q但是通常使用你的DBMS所指定的特定语a。Oracle使用PL/SQLQPostgreSQL使用pl/pgsqlQDB2使用Procedural SQL。这些语a都非常相伹{在它们之间UL存储q程q不比在Sun的EJB规范不同实现版本之间ULSession Bean困难。ƈ且,存储q程是ؓ嵌入SQL所设计Q这使得它们比Java或C{语a更加友好地方式表达数据库的机制?
因ؓ存储q程q行在DBMS自nQ这可以帮助减少应用E序中的{待旉。不是在Java代码中执?个或5个SQL语句Q而只需要在服务器端执行1个存储过E。网l上的数据往q次数的减少可以戏剧性地优化性能?

使用存储q程

单的老的JDBC通过CallableStatementcL持存储过E的调用。该cd际上是PreparedStatement的一个子cR假设我们有一个poets数据库。数据库中有一个设|诗人逝世q龄的存储过E。下面是对老酒鬼Dylan ThomasQold soak Dylan ThomasQ不指定是否有关典故、文化,h评指正。译注)q行调用的详l代码:

try
{
    int age = 39;
    String poetName = "dylan thomas";
    CallableStatement proc =
        connection.prepareCall("{ call set_death_age(?, ?) }");
    proc.setString(1, poetName);
    proc.setInt(2, age);
    cs.execute();
}
catch (SQLException e)
{
    // ....
}

传给prepareCallҎ(gu)的字串是存储q程调用的书写规范。它指定了存储过E的名称Q?代表了你需要指定的参数?
和JDBC集成是存储过E的一个很大的便利Qؓ了从应用中调用存储过E,不需要存根(stubQ类或者配|文Ӟ除了你的DBMS的JDBC驱动E序外什么也不需要?
当这D代码执行时Q数据库的存储过E就被调用。我们没有去获取l果Q因存储q程q不q回l果。执行成功或p|通过例外得知。失败可能意味着调用存储q程时的p|Q比如提供的一个参数的cd不正)Q或者一个应用程序的p|Q比如抛Z个例外指C在poets数据库中q不存在“Dylan Thomas”)

l合SQL操作与存储过E?

映射Java对象到SQL表中的行相当单,但是通常需要执行几个SQL语句Q可能是一个SELECT查找IDQ然后一个INSERT插入指定ID的数据。在高度规格化(W合更高的范式,译注Q的数据库模式中Q可能需要多个表的更斎ͼ因此需要更多的语句。Java代码会很快地膨胀Q每一个语句的|络开销也迅速增加?
这些SQL语句转移C个存储过E中大大简化代码,仅涉及一ơ网l调用。所有关联的SQL操作都可以在数据库内部发生。ƈ且,存储q程语言Q例如PL/SQLQ允怋用SQL语法Q这比Java代码更加自然。下面是我们早期的存储过E,使用Oracle的PL/SQL语言~写Q?

create procedure set_death_age(poet VARCHAR2, poet_age NUMBER)
    poet_id NUMBER;
begin
  SELECT id INTO poet_id FROM poets WHERE name = poet;
  INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age);
end set_death_age;

很独特?不。我打赌你一定期待看C个poets表上的UPDATE。这也暗CZ使用存储q程实现是多么容易的一件事情。set_death_age几乎可以肯定是一个很烂的实现。我们应该在poets表中d一列来存储逝世q龄。Java代码中ƈ不关心数据库模式是怎么实现的,因ؓ它仅调用存储q程。我们以后可以改变数据库模式以提高性能Q但是我们不必修Ҏ(gu)们代码?
下面是调用上面存储过E的Java代码Q?

public static void setDeathAge(Poet dyingBard, int age)
    throws SQLException
{
   Connection con = null;
   CallableStatement proc = null;

   try
   {
      con  = connectionPool.getConnection();
      proc = con.prepareCall("{ call set_death_age(?, ?) }");
      proc.setString(1, dyingBard.getName());
      proc.setInt(2, age);
      proc.execute();
   }
   finally
   {
      try
      {
         proc.close();
      }
      catch (SQLException e) {}
      con.close();
   }
}

Z保可维护性,使用像这儿这LstaticҎ(gu)。这也得调用存储过E的代码集中在一个简单的模版代码中。如果你用到许多存储q程Q就会发C需要拷贝、粘贴就可以创徏新的Ҏ(gu)。因Z码的模版化,甚至也可以通过脚本自动生调用存储q程的代码?

Functions

存储q程可以有返回|所以CallableStatementcLcMgetResultSetq样的方法来获取q回倹{当存储q程q回一个值时Q你必须使用registerOutParameterҎ(gu)告诉JDBC驱动器该值的SQLcd是什么。你也必调整存储过E调用来指示该过E返回一个倹{?
下面接着上面的例子。这ơ我们查询Dylan Thomas逝世时的q龄。这ơ的存储q程使用PostgreSQL的pl/pgsqlQ?

create function snuffed_it_when (VARCHAR) returns integer '
declare
    poet_id NUMBER;
    poet_age NUMBER;
begin
    -- first get the id associated with the poet.
    SELECT id INTO poet_id FROM poets WHERE name = $1;
    -- get and return the age.
    SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;
    return age;
end;
' language 'pl/pgsql';

另外Q注意pl/pgsql参数名通过Unix和DOS脚本?n语法引用。同Ӟ也注意嵌入的注释Q这是和Java代码相比的另一个优性。在Java中写q样的注释当然是可以的,但是看v来很凌ؕQƈ且和SQL语句pQ必d入到Java String中?
下面是调用这个存储过E的Java代码Q?

connection.setAutoCommit(false);
CallableStatement proc =
    connection.prepareCall("{ ? = call snuffed_it_when(?) }");
proc.registerOutParameter(1, Types.INTEGER);
proc.setString(2, poetName);
cs.execute();
int age = proc.getInt(2);

如果指定了错误的q回值类型会怎样Q那么,当调用存储过E时抛Z个RuntimeExceptionQ正如你在ResultSet操作中用了一个错误的cd所到的一栗?

复杂的返回?

关于存储q程的知识,很多人好像就熟?zhn)我们所讨论的这些。如果这是存储过E的全部功能Q那么存储过E就不是其它q程执行机制的替换方案了。存储过E的功能比这强大得多?
当你执行一个SQL查询ӞDBMS创徏一个叫做cursorQ游标)的数据库对象Q用于在q回l果中P代每一行。ResultSet是当前时间点的游标的一个表C。这是Z么没有缓存或者特定数据库的支持,你只能在ResultSet中向前移动?
某些DBMS允许从存储过E中q回游标的一个引用。JDBCq不支持q个功能Q但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针QpointerQ?
设想列出所有没有活到退休年龄的诗hQ下面是完成q个功能的存储过E,q回一个打开的游标,同样也用PostgreSQL的pl/pgsql语言Q?

create procedure list_early_deaths () return refcursor as '
declare
    toesup refcursor;
begin
    open toesup for
        SELECT poets.name, deaths.age
        FROM poets, deaths
        -- all entries in deaths are for poets.
        -- but the table might become generic.
        WHERE poets.id = deaths.mort_id
            AND deaths.age < 60;
    return toesup;
end;
' language 'plpgsql';

下面是调用该存储q程的JavaҎ(gu)Q将l果输出到PrintWriterQ?
PrintWriter:

static void sendEarlyDeaths(PrintWriter out)
{
    Connection con = null;
    CallableStatement toesUp = null;
    try
    {
        con = ConnectionPool.getConnection();

        // PostgreSQL needs a transaction to do this...
        con.setAutoCommit(false);

        // Setup the call.
        CallableStatement toesUp
            = connection.prepareCall("{ ? = call list_early_deaths () }");
        toesUp.registerOutParameter(1, Types.OTHER);
        getResults.execute();

        ResultSet rs = (ResultSet) getResults.getObject(1);
        while (rs.next())
        {
            String name = rs.getString(1);
            int age = rs.getInt(2);
            out.println(name + " was " + age + " years old.");
        }
        rs.close();
    }
    catch (SQLException e)
    {
        // We should protect these calls.
        toesUp.close();
        con.close();
    }
}

因ؓJDBCq不直接支持从存储过E中q回游标Q我们用Types.OTHER来指C存储过E的q回cdQ然后调用getObject()Ҏ(gu)q对q回D行强制类型{换?
q个调用存储q程的JavaҎ(gu)是mapping的一个好例子。Mapping是对一个集上的操作q行抽象的方法。不是在q个q程上返回一个集Q我们可以把操作传送进L行。本例中Q操作就是把ResultSet打印C个输出流。这是一个值得举例的很常用的例子,下面是调用同一个存储过E的另外一个方法实玎ͼ

public class ProcessPoetDeaths
{
    public abstract void sendDeath(String name, int age);
}

static void mapEarlyDeaths(ProcessPoetDeaths mapper)
{
    Connection con = null;
    CallableStatement toesUp = null;
    try
    {
        con = ConnectionPool.getConnection();
        con.setAutoCommit(false);

        CallableStatement toesUp
            = connection.prepareCall("{ ? = call list_early_deaths () }");
        toesUp.registerOutParameter(1, Types.OTHER);
        getResults.execute();

        ResultSet rs = (ResultSet) getResults.getObject(1);
        while (rs.next())
        {
            String name = rs.getString(1);
            int age = rs.getInt(2);
            mapper.sendDeath(name, age);
        }
        rs.close();
    }
    catch (SQLException e)
    {
        // We should protect these calls.
        toesUp.close();
        con.close();
    }
}

q允许在ResultSet数据上执行Q意的处理Q而不需要改变或者复制获取ResultSet的方法:

static void sendEarlyDeaths(final PrintWriter out)
{
    ProcessPoetDeaths myMapper = new ProcessPoetDeaths()
    {
        public void sendDeath(String name, int age)
        {
            out.println(name + " was " + age + " years old.");
        }
    };
    mapEarlyDeaths(myMapper);
}

q个Ҏ(gu)使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeathҎ(gu)的一个实玎ͼ和我们上面的例子一L方式把结果写入到输出。当Ӟq个技巧ƈ不是存储q程Ҏ(gu)的,但是和存储过E中q回的ResultSetl合使用Q是一个非常强大的工具?

l论

存储q程可以帮助你在代码中分逻辑Q这基本上L有益的。这个分ȝ好处有:
&#8226; 快速创建应用,使用和应用一h变和改善的数据库模式。?
&#8226; 数据库模式可以在以后改变而不影响Java对象Q当我们完成应用后,可以重新设计更好的模式?
&#8226; 存储q程通过更好的SQL嵌入使得复杂的SQL更容易理解?
&#8226; ~写存储q程比在Java中编写嵌入的SQL拥有更好的工PQ大部分~辑器都提供语法高亮Q?
&#8226; 存储q程可以在Q何SQL命o行中试Q这使得调试更加Ҏ(gu)?

q不是所有的数据库都支持存储q程Q但是存在许多很的实现Q包括免?开源的和非免费的,所以移植ƈ不是一个问题。Oracle、PostgreSQL和DB2都有cM的存储过E语aQƈ且有在线的社区很好地支持?
存储q程工具很多Q有像TOAD或TORAq样的编辑器、调试器和IDEQ提供了~写、维护PL/SQL或pl/pgsql的强大的环境?
存储q程实增加了你的代码的开销Q但是它们和大多数的应用服务器相比,开销得多。如果你的代码复杂到需要用DBMSQ我整个采用存储q程的方式?

资源

&#8226; JDBC specification 
&#8226; PostgreSQL 
&#8226; Oracle Corporation's Oracle database server 
&#8226; IBM's DB2 database server 

作者简介:Nic Ferrier 是Web应用斚w的独立Y仉问。?



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=629847



風向逆轉 - p爪哇 2006-03-22 03:26 发表评论
]]>
[收藏]谈谈JDBC接口技?/title><link>http://www.tkk7.com/iKingQu/articles/36756.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Tue, 21 Mar 2006 19:24:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/36756.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/36756.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/36756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/36756.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/36756.html</trackback:ping><description><![CDATA[ <div id="gibuqgw" class="postText"> <p> <span id="ingsafg" class="Title">谈谈JDBC接口技?/span> <br />--------------------------------------------------------------------------------<br /> <br />   JDBC是一U可用于执行SQL语句的JavaAPIQApplicationProgrammingInterface应用E序设计接口Q。它׃些Java语言~写的类和界面组成。JDBC为数据库应用开发h员、数据库前台工具开发h员提供了一U标准的应用E序设计接口Q开发h员可以用UJava语言~写完整的数据库应用E序。?</p> <p>    一、ODBC到JDBC的发展历E?</p> <p>    说到JDBCQ很Ҏ(gu)让h联想到另一个十分熟(zhn)的字眼“ODBC”。它们之间有没有联系呢?如果有,那么它们之间又是怎样的关pdQ?</p> <p>    ODBC是OpenDatabaseConnectivity的英文简写。它是一U用来在相关或不相关的数据库理pȝQDBMSQ中存取数据的,用C语言实现的,标准应用E序数据接口。通过ODBCAPIQ应用程序可以存取保存在多种不同数据库管理系l(DBMSQ中的数据,而不论每个DBMS使用了何U数据存储格式和~程接口。?</p> <p>    1QODBC的结构模型?<br />    ODBC的结构包括四个主要部分:应用E序接口、驱动器理器、数据库驱动器和数据源。?<br />    应用E序接口Q屏蔽不同的ODBC数据库驱动器之间函数调用的差别,为用h供统一的SQL~程接口。?<br />    驱动器管理器Qؓ应用E序装蝲数据库驱动器。?<br />    数据库驱动器Q实现ODBC的函数调用,提供对特定数据源的SQLh。如果需要,数据库驱动器修改应用程序的hQ得请求符合相关的DBMS所支持的文法。?<br />    数据源:qh要存取的数据以及与它相关的操作系l、DBMS和用于访问DBMS的网l^台组成。?</p> <p>    虽然ODBC驱动器管理器的主要目的是加蝲数据库驱动器Q以便ODBC函数调用Q但是数据库驱动器本w也执行ODBC函数调用Qƈ与数据库怺配合。因此当应用pȝ发出调用与数据源q行q接Ӟ数据库驱动器能管理通信协议。当建立起与数据源的q接Ӟ数据库驱动器便能处理应用pȝ向DBMS发出的请求,对分析或发自数据源的设计q行必要的翻译,q将l果q回l应用系l。?</p> <p>    2QJDBC的诞生?</p> <p>    自从Java语言?995q?月正式公布以来,Java风靡全球。出现大量的用java语言~写的程序,其中也包括数据库应用E序。由于没有一个Java语言的APIQ编Eh员不得不在JavaE序中加入C语言的ODBC函数调用。这׃很多Java的优UҎ(gu)无法充分发挥,比如q_无关性、面向对象特性等。随着来多的编Eh员对Java语言的日益喜爱,来多的公司在JavaE序开发上投入的精力日益增加,对java语言接口的访问数据库的API的要求越来越强烈。也׃ODBC的有其不之处,比如它ƈ不容易用,没有面向对象的特性等{,SUN公司军_开发一Java语言为接口的数据库应用程序开发接口。在JDK1Qx版本中,JDBC只是一个可选部ӞCJDK1Q?公布ӞSQLcdQ也是JDBCAPIQ就成ؓJava语言的标准部件。?</p> <p>    二、JDBC技术概qW?</p> <p>    JDBC是一U可用于执行SQL语句的JavaAPIQApplicationProgrammingInterfaceQ应用程序设计接口)。它׃些Java语言写的cR界面组成。JDBCl数据库应用开发h员、数据库前台工具开发h员提供了一U标准的应用E序设计接口Q开发h员可以用UJava语言~写完整的数据库应用E序。?</p> <p>    通过使用JDBCQ开发h员可以很方便地将SQL语句传送给几乎M一U数据库。也是_开发h员可以不必写一个程序访问SybaseQ写另一个程序访问OracleQ再写一个程序访问Microsoft的SQLServer。用JDBC写的E序能够自动地将SQL语句传送给相应的数据库理pȝQDBMSQ。不但如此,使用Java~写的应用程序可以在M支持Java的^Cq行Q不必在不同的^C~写不同的应用。Java和JDBC的结合可以让开发h员在开发数据库应用时真正实现“WriteOnceQRunEverywhereQ”?</p> <p>    Javah健壮、安全、易用等Ҏ(gu),而且支持自动|上下蝲Q本质上是一U很好的数据库应用的~程语言。它所需要的是Java应用如何同各U各L数据库连接,JDBC正是实现q种q接的关键。?</p> <p>    JDBC扩展了Java的能力,如用Java和JDBCAPI可以公布一个Web,中带有能访问远端数据库的Ap?plet。或者企业可以通过JDBC让全部的职工Q他们可以用不同的操作pȝQ如WindwosQMachintosh和UNIXQ在In?tranet上连接到几个全球数据库上Q而这几个全球数据库可以是不相同的。随着来多的程序开发h员用Java语言Q对Java讉K数据库易操作性的需求越来越强烈。?</p> <p>    MIS理人员喜欢Java和JDBCQ因样可以更Ҏ(gu)l济地公布信息。各U已l安装在数据库中的事务处理都l正常运行,甚至q些事务处理是存储在不同的数据库理pȝ中;而对新的数据库应用来_开发时间将~短Q安装和版本升񔞮大大简化。程序员可以~写或改写一个程序,然后它攑֜服务器上Q而每个用户都可以讉K服务器得到最新的版本。对于信息服务行业,Java和JDBC提供了一U很好的向外界用hC息的Ҏ(gu)。?</p> <p>    1QJDBC的Q务?</p> <p>    单地_JDBC能完成下列三件事Q?<br />    1Q同一个数据库建立q接Q?<br />    2Q向数据库发送SQL语句Q?<br />    3Q处理数据库q回的结果。?</p> <p>    2QJDBC一U底层的API  </p> <p>    JDBC是一U底层APIQ这意味着它将直接调用SQL命o。JDBC完全胜Qq个dQ而且比其他数据库互联更加Ҏ(gu)实现。同时它也是构造高层API和数据库开发工L基础。高层API和数据库开发工具应该是用户界面更加友好Q用更加方便,更易于理解的。但所有这LAPI最l被译JDBCq样的底层API。目前两U基于JDBC的高层API正处在开发阶Dc?</p> <p>    1QSQL语言嵌入Java的预处理器。虽然DBMS已经实现了SQL查询Q但JDBC要求SQL语句被当作字W串参数传送给JavaE序。而嵌入式SQL预处理器允许E序员将SQL语句LQJava变量可以在SQL语句中用,来接收或提供数倹{然后SQL的预处理器将把这UJavaQSQLL的程序翻译成带有JDBCAPI的JavaE序。?</p> <p>    2Q实C关系数据库到Javacȝ直接映射。Javasoft和其他公司已l宣布要实现q一技术。在q种“对象/关系”映中Q表的每一行都变成这cȝ一个实例,每一列的值对应实例的一个属性。程序员可以直接操作Java的对象;而存取所需要的SQL调用在内部直接产生。还可以实现更加复杂的映,比如多张表的行在一个Java的类中实现。?</p> <p>    随着大家对JDBC兴趣的不断浓厚,来多的开发h员已l开始利用JDBC为基的工兯行开发。这使开发工作变得容易。同ӞE序员也正在开发对最l用h说访问数据库更加Ҏ(gu)的应用程序。?</p> <p>    3QJDBC和ODBC及其他API的比较?</p> <p>    到目前ؓ止,微Y的ODBC可能是用得最q泛的访问关pL据库的API。它提供了连接几乎Q何一U^台、Q何一U数据库的能力。那么,Z么不直接从Java中直接用ODBC呢?  </p> <p>    回答是可以从Java中用ODBCQ但最好在JDBC的协助下Q用JDBCQODBC桥接器实现。那么,Z么需要JDBC呢?要回{这个问题,有这么几个方面:  </p> <p>    1QODBCq不适合在Java中直接用。ODBC是一个C语言实现的APIQ从JavaE序调用本地的CE序会带来一pdcM安全性、完整性、健壮性的~点。?</p> <p>    2Q其ơ,完全_地实CC代码ODBC到JavaAPI写的ODBC的翻译也q不令h满意。比如,Java没有指针Q而ODBC中大量地使用了指针,包括极易出错的空指针“voidQ”。因此,对JavaE序员来_把JDBC设想成将ODBC转换成面向对象的API是很自然的。?</p> <p>    3QODBCq不Ҏ(gu)学习Q它?yu)简单特性和复杂Ҏ(gu)؜杂在一P甚至寚w常简单的查询都有复杂的选项。而JDBC刚好相反Q它保持了简单事物的单性,但又允许复杂的特性。?</p> <p>    4QJDBCq样的JavaAPI对于UJavaҎ(gu)来说是必ȝ。当使用ODBCӞZ必须在每一台客h上安装ODBC驱动器和驱动理器。如果JDBC驱动器是完全用Java语言实现的话Q那么JDBC的代码就可以自动的下载和安装Qƈ保证其安全性,而且Q这适应MJavaq_Q从|络计算机NC到大型主机Mainframe。?</p> <p>    总而言之,JDBCAPI是能体现SQL最基本抽象概念的、最直接的Java接口。它建构在ODBC的基上,因此Q熟(zhn)ODBC的程序员发现学习JDBC非常Ҏ(gu)。JDBC保持了ODBC的基本设计特征。实际上Q这两种接口都是ZXQOPENSQL的调用接口QCLIQ。它们的最大的不同是JDBC是基于Java的风格和优点Qƈ强化了Java的风格和优点。?</p> <p>    最q,微Y又推Z除了ODBC以外的新的APIQ如RDOQADO和OLEDB。这些API事实上在很多斚w上同JDBC一h着相同的方向努力,也就是努力成Z个面向对象的Q基于ODBC的类接口。然而,q些接口目前q不能代替ODBCQ尤其在ODBC驱动器已l在市场完全形成的时候,更重要的是它们只是ODBC的“漂亮的包装”。?</p> <p>    4QJDBC两层模型和三层模型?</p> <p>    JDBC支持两层模型Q也支持三层模型讉K数据库?两层模型中,一个java Appple或者一个JAQva应用直接同数据库q接。这需要能直接被访问的数据库进行连接的JDBC驱动器。用LSQL语句被传送给数据库,而这些语句执行的l果被传回l用戗数据库可以在同一机器上,也可以另一机器上通过|络q行q接。这被称为“Client/Server”结构,用户的计机作ؓClient,q行数据库的计算Z为Server。这个网l可是intranetQ比如连接全体雇员的企业内部|,当然也可以是internet。?</p> <p>    在三层模型中Q命令将被发送到服务的“中间层”,而“中间层”将SQL语句发送到数据库。数据库处理SQL语句q将l果q回“中间层”,然后“中间层”将它们 q回用户。MIS理员将发现三层模型很有吸引力,因ؓ“中间层”可以进行对讉K的控制ƈ协同数据库的更新Q另一个优势就是如果有一个“中间层”用户就可以使用一个易用的高层的APIQ这个API可以由“中间层”进行{换,转换成底层的调用。而且Q在许多情况下,三层模型可以提供更好的性能。?</p> <p>    到目前ؓ止,“中间层”通常q是用C或C++实现Q以保证光性能。但随着优化~译器的引入Q将java的字节码转换成高效的机器码,用java来实现“中间层”将来实际。而JDBC是允总一个java“中间层”访问数据库的关键?</p> <br /> <br /> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=629840</p> </div> <img src ="http://www.tkk7.com/iKingQu/aggbug/36756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-22 03:24 <a href="http://www.tkk7.com/iKingQu/articles/36756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]JDBC 4.0规范之目?/title><link>http://www.tkk7.com/iKingQu/articles/36755.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Tue, 21 Mar 2006 19:23:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/36755.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/36755.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/36755.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/36755.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/36755.html</trackback:ping><description><![CDATA[ <div id="dwaptud" class="postText"> <p> <span id="mungzlu" class="Title">JDBC 4.0规范之目?/span> <br />--------------------------------------------------------------------------------<br /> <br />  历史</p> <p>  JDBC API是一U成熟的技术,最早发布是1997q?月。在最初的版本中,JDBC API着重提供一个对SQL数据库的基本调用U接口。之后,JDBC 2.1规范?.0可选包规范拓宽了API的范围。包括支持更高应用和管理用JDBC API来增强其应用的应用服务所需的各特征?/p> <p>  JDBC 3.0规范以填补较?yu)范围内的功能缺׃ؓ目标。对于JDBC 4.0Q我们的目标有两个:提高所有开发者在JAVAq_使用SQL开发的易用性。第二,提供企业U特性的JDBC工具集和API来管理JDBC资源?<br />  目标概述</p> <p>  下面列出了一般的JDBC API和JDBC 4.0 API的目标和设计原理Q?/p> <p>  1.适合J2EE和J2SEq_</p> <p>  JDBC API是JAVAq_的重要技术。JDBC 4.0 API应遵循JAVA 2 企业版和JAVA 2 标准版^台的M方向。另外,最q开发的JAVA 5.0q_已经展示Zpd新的Ҏ(gu)和语言的改q,q在本规范中q泛使用?/p> <p>  2.兼容SQL:2003</p> <p>  JDBC API提供用JAVA~程语言~写标准SQL来对应用q行E序U访问能力。JDBC 3.0致力于确保其可以支持可广泛支持工业的hSQL:99特征的子集。对于JDBC 4.0也一P支持SQL:2003是本规范的一个主要组成部分。我们期望在不久的将来可以实现?/p> <p>  3.巩固以前的规?/p> <p>  本文档把4个以前的JDBC规范l织成一个单一的JDBC API规范?/p> <p>  4.提供中立于开发商的一般访问特?/p> <p>  JDBC API致力于提供支持针对不同开发商应用的高带宽的一般访问特征。其目标是提供与原生应用可以辑ֈ的同U别的访问特性。然而,本API必须_通用和灵zM适应大范围的实施?/p> <p>  5.x于SQL</p> <p>  JDBC API一直关注于用JAVA~程语言讉K相关数据。这个目标曾在JDBC 3.0 API规范中说明,在本规范中仍是一个主要原则。提供API和工h改进开发难度,ql集中于在JAVAq_开发基于SQL的Y件的需要。与以前的规范相|本规范也不阻止与其它技术进行交互,如XMLQCORBA和非关系型数据?/p> <p>  6.提供基础数据和更高别的API</p> <p>  JDBC API提供标准API访各U数据源或旧pȝ。实施的差异佉K过JDBC API抽象透明化。这使其成ؓҎ(gu)开发可Ud工具和应用的工具开发商来说Q一个有价值的目标q_?/p> <p>  ׃它是一个用JAVA~程语言对SQL的“调用”接口Q所以JDBC API也适用于更高别应用的底层Q如EJB 3.0容器理的持久性,SQLJ和JDBC的RowSet实现?/p> <p>  7.保持?/p> <p>  JDBC API意欲成ؓ一U用简单、直接的接口。在之上可以构徏更多复杂的实体。这个目标通过定义大量紧凑、单一目的Ҏ(gu)来代替少数带有控制标识参数的复杂、多目的的方法来实现?/p> <p>  8.增强可靠性、可用行和可?/p> <p>  可靠性、可用行和可性是J2EE和J2SEq_的主题,也是未来JAVAq_的主题。JDBC 4.0 API严格按照以上目标q行。它扩展支持了一些领域,包括资源理、对逻辑q接预备声明的复用和错误处理?/p> <p>  9.支持对已有应用和驱动的向后兼?/p> <p>  使用已有JDBC技术的驱动和应用必能够在支持JDBC 4.0 API的JAVA虚拟Zl箋工作。那些只使用更早版本中定义的JDBC APIQ不包括在JDBC 2.0中已废除的)的应用,应该不需要修改就可以l箋q行。已有的应用应该可以直接q移到JDBC 4.0技术?/p> <p>  10.与JDBC RowSet工具紧密联系</p> <p>  J2SE 5.0包含一个标准JDBC RowSet工具Q在《JDBC RowSet工具集》中说明QJSR-114Q)。本规范会提供一个工具集包括工具cȝ别和元数据语aU别的工兗它允许开发者轻易的把用JDBC技术的应用q移到JDBC RowSet模型。该模型可以断开数据源访问连接,另外能够理来自于XMLȝ点的关系数据存储?/p> <p>  11.允许对连接器的向前兼?/p> <p>  q接器构架定义了一个标准方法来对资源适配器进行打包和布v。它允许一个J2EE容器整合它与外部资源的连接、处理和安全理。JDBC 4.0 API提供JDBC驱动到连接器架构的迁U\径。对那些产品中用JDBC技术的开发商来说Q应可以转向对连接器API的实现。希望这些实C重新包装已有数据源的实现。这样他们可以对q接器框架进行复用?</p> <p>  12.清晰的列明需?/p> <p>  遵从JDBC要求的需求,要明和易于识别。JDBC 4.0规范和API文档QJavadocQ会明晰什么特性是需要的Q什么特性是可选的?/p> <br /> <br /> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=629584</p> </div> <img src ="http://www.tkk7.com/iKingQu/aggbug/36755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-22 03:23 <a href="http://www.tkk7.com/iKingQu/articles/36755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]JDBCq接Oracle数据库常见问题及解决Ҏ(gu)http://www.tkk7.com/iKingQu/articles/36519.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 16:27:00 GMThttp://www.tkk7.com/iKingQu/articles/36519.htmlhttp://www.tkk7.com/iKingQu/comments/36519.htmlhttp://www.tkk7.com/iKingQu/articles/36519.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36519.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36519.html
  • Jbuilder正确q接 oracle 9i需要注意的几个问题
    • oracle8以上的应该都使用classes12.jar文g作ؓjdbc驱动Q?
    • 正确讄windows的classpath和jbuilder中的enterprise setup 、configure librariesQ将casses12.jar路径正确dCq需要设|的地方Q?strong>
    • q入database pilotQ在database pilot中,file---new 在driver列表中如果oracle的驱动是U色的,p明你的oralce在jb中加载失败;
    • 若③没有错,则新Z个urlQjdbc:oracle:thin:@QyourhostnameQ?1521:Qyour sidQ?strong>
    • q接数据库的Username/password

    ?大部分站友的jbuilderq接oracle的问题都是由于没有正配|classpath{引L?/p>

  • 使用非XA方式q接ORACLE数据?

    在windows下配|Oracle_XA时要注意两点Q?/p>

    #ORACLE 10
    Oracle_XA;xaosw;%ORACLE_HOME% dbms oraxa10.lib%ORACLE_HOME%precompibmsvcorasql10.lib

    #oracle 9
    Oracle_XA;xaosw;%ORACLE_HOME% dbms oraxa9.lib%ORACLE_HOME%precompibmsvcorasql9.lib

    Unix?br />Oracle_XA:xaosw:....

    W一Q在windows ?ORACLE_XA 和xaosw后面的是分号";"Q不是冒?:"
    W二Q上面的q些LIB写在一行上Q中间用I格分开Q如果没有在pȝ的环境变量中讄ORACLE_HOMEQ就写绝对\径?/p>

  • JDBC操作ORACLE数据库时出现‘java.sql.SQLException:IO异常Q不在流模式下?
    1. 用OracleStatmentQ,不要用java.sql.Statment
    2. 如果对已有连接进行setAutoCommitp|Q则关闭该连接ƈ重新建立一个连?
    3. 到ORACLE站点下蝲一个最新的JDBC DriverQ如果操作LOBcdQ用ORACLE自带的接口和c?
  • weblogicq接oracle问题QThe Network Adapter could not establish the connection

    可能是服务器的监听停掉了Q是数据库的问题Q与应用无关Q应该先查一下oracle是否正常Q用sql*plusq接一下数据库Q看能否正常q接Q?/p>

  • Weblogic中用Oracleq接池及Oracle备䆾的注意事?

    使用HP-UNIXQWeblogic 8.1,Oracle 9.2.0.5
    配置了一个普通的q接?驱动E序采用oracle的Oracle’s Driver(Thin) version 9.0.1, 9.2.0

    错误情况Q?br />l果使用数据库连接池时报错,说没有连接池资源了。实际上数据库的q接池完全空Ԍq且试也是对的QOracle也是正常可以q接、用的?/p>

    问题Ҏ(gu)Q?br />通过层层排错Q发现原来后台在使用Oracle的exp备䆾一个只有同义词的用PDexpq程僉|?br />杀死exp、重启Oracle{无法解决问题,最l重启UNIXQ禁止备份只有同义词的用P问题解决?/p>

    ȝQ?br />应该是Oracle9的exp BUGDq接池问题,不要使用exp倒出同义?/p>

  • q接Oracle时抛出如下异常:java.sql.SQLException: Io exception:The Network Adapter could not establish connection一U生原?

    Oracle Database Connection (from oracle.com)
    PROBLEM
    You are attempting to connect to an Oracle instance using JDBC and you are receiving the following error. 
       java.sql.SQLException: Io exception:
         The Network Adapter could not establish connection
       SQLException: SQLState (null) vendor code (17002)
    Any or all of the following conditions may also apply:
    1) You are able to establish a SQL*Plus connection from the same
       client to the same Oracle instance.
    2) You are able to establish a JDBC OCI connection, but not a Thin
       connection from the same client to the same Oracle instance.
    3) The same JDBC application is able to connect from a different
       client to the same Oracle instance.
    4) The same behavior applies whether the initial JDBC connection
       string specifies a hostname or an IP address.
    REDISCOVERY 
    To verify whether you are hitting this problem, verify whether the Oracle instance is configured for Multithreaded Server (MTS). If the Oracle instance is not configured for MTS, you are probably encountering a different problem. Otherwise, continue. Try forcing the JDBC connection to use a dedicated server instead of a shared server. This can be accomplished in several ways. For JDBC OCI or Thin, this can be done by reconfiguring the server for dedicated connections only. This approach, however, may not be feasible in many cases. In such cases, the following options apply: For JDBC OCI:  
    1) Add the (SERVER=DEDICATED) property to the TNS connect string
       stored in the tnsnames.ora file on the client.
    2) Set the user_dedicated_server=ON in sqlnet.ora on the client.
    For JDBC Thin:
    You must specify a full name-value pair connect string (the same as it might appear in the tnsnames.ora file) instead of the short JDBC Thin syntax. For example, instead of
    "jdbc:oracle:thin::port:sid"
    you would need to use a string of the form
    "jdbc:oracle:thin:@(DESCRIPTION="                    +
                           "(ADDRESS_LIST="              +
                               "(ADDRESS=(PROTOCOL=TCP)" +
                                        "(HOST=host)"    +                                      =
                                        "(PORT=port)"    +
                               ")"                       +
                           ")"                           +
                           "(CONNECT_DATA="              +
                               "(SERVICE_NAME=sid)"      +
                               "(SERVER=DEDICATED)"      +
                           ")"                           +
                         ")"
    If the connection works fine after having made these changes, it is very likely that this is the problem you are encountering. In this case, one last test will help to verify this fact.
    Log into the remote host on which the Oracle instance is running and execute the appropriate command to determine what the server 'thinks' its hostname is (i.e. the name that was configured when the server was installed and configured). For example, on a Unix host the 'hostname' command can be used for this purpose.
    Using the name displayed (e.g. by the hostname command), exactly as it appeared (i.e. if the output from the hostname command had the domain name included, then include it), return to the client which was unable to connect and try pinging the server.
    NOTE: It is critical that you attempt to ping the server using EXACTLY the same hostname you got from the server.
    If you are unable to ping the server via this hostname, then you almost certainly hitting this problem. If not, this may be a new issue, but at least you will have found a workaround (i.e. use a dedicated connection).
    EXPLANATION 
    To understand why this problem occurs, one must first understand the differences in how the listener handles connections to shared servers versus dedicated servers.
    When connecting to a dedicated server, the client connects to the listener (via hostname or IP address). The listener then spawns a dedicated server process and hands off the socket used to accept the client connection to that server. The client and server then start communicating via the endpoints established by the initial connection. NOTE: There is only one connection in this case. When connecting to a shared server, the initial client connection to the listener is the same. However, with MTS, there is no need to spawn a new server process; a pool of shared processes already exists. Also, clients do not communicate directly with the server processes in MTS; rather, they communicate with a dispatcher.
    For this reason, when setting up an MTS connection, the listener sends a redirect message back to the client asking the client to close the connection to the listener and connect to a dispatcher. The information in this message includes the hostname and a port number for the appropriate dispatcher. The redirect message will ALWAYS specify a hostname, even if the client initially provided an IP address.
    If, for any reason, the hostname provided to the listener (e.g. by the 'hostname' or another command) doesn't agree with the hostname by which the server is known on the client, the connection fails.
    On the other hand, if "(SERVER=DEDICATED)" already appears in the TNS connect string in tnsnames.ora or if "use_dedicated_server=ON" already appears in the sqlnet.ora file, you may find that SQL*Plus and/or JDBC OCI work fine, while JDBC Thin fails.
    SOLUTION 
    Obviously, one solution is to use dedicated servers. However, this may not always be feasible.
    The key is to make sure the hostname on both the client and server agree. This can be accomplished by reconfiguring either the client or the server, but there are things to be aware of in both cases.
    If the server is configured to return a different hostname, then it is possible that other clients which used to work will now fail.
    In some cases, it may not be feasible to reconfigure the client. For example, if the server version of the hostname does not include the domain, you would need to remove the domain portion of the hostname on the client; but, if the client needs to connect to more than one server with the same base name in different domains, this may not be possible, as the hostname may be ambiguous.
    REFERENCES 
    bug:1269734 java.sql.SQLException: Io exception: The Network Adapter could not be found.

  • q接ORACLE数据库报错:javax.naming.NameNotFoundException: Unable to resolve oracThin. Resolved: '' Unresolved:'oracThin' ; remaining name '' 

    问题描述Q配|完JDBC后,打开面的时候,报出如下错误信息Q?br />javax.naming.NameNotFoundException: Unable to resolve oracThin. Resolved: '' Unresolved:'oracThin' ; remaining name ''
    JDBC配置如下Q?br />Connection Pools(q接?
    Name:OracThin
    URL:jdbc:oracle:thin.0.0.1:LYSIMIS
    Driver Classname:oracle.jdbc.driver.OracleDriver
    Properties:
    user=system
    password=manager
    dll=ocijdbc8
    protocol=thin
    数据源配|如下:
    Name:OracThin
    JNDI Name:OracThin
    Pool Name:OracThin
    当程序执行到q一步时出错?br />ctx = new InitialContext();
    ds = (javax.sql.DataSource)ctx.lookup ("OracThin"); 

    问题解决后汉字是q 

    错误产生原因及解军_法:

    • URL:jdbc:oracle:thin:.0.0.1:1521:LYSIMIQthin后面?,127.0.0.1后面加端口号
    • 注意名字大小?
    • target 到server?
    • 再看看pool是否h了,没v来的?重vweblogic
    • q问题QJava是基于UnicodeQ:
      • 在JSP 文g中加?lt;%@ page contentType="text/html; charset=GBK" %>
      • 在weblogic.xml文g?lt;jsp-descriptor>部分加入
        <jsp-descriptor>
        <jsp-param>
        <param-name>compilerSupportsEncoding</param-name>
        <param-value>true</param-value>
        </jsp-param>
        <jsp-param>
        <param-name>encoding</param-name>
        <param-value>GBK</param-value>
        </jsp-param>
        </jsp-descriptor>
  • oracle XA的疑?

    问题描述QOracle_XA;xaosw;D:oracleora92 dbmsXAORAXA9.lib C:msvcoraSQL9.lib?br />xaosw是什么意?/p>

    解答Q可以参考ORACLE的XA部分的文档?/p>

    http://www-rohan.sdsu.edu/doc/oracle/server803/A54642_01/ch_xa.htm

  • oracle与weblogic自动启动与停?

    问题描述Q每ơ重新启动服务器时oracle数据库若没有关闭Q则必须先关闭后在重新启动redhat advance serverQoracle才能够正常运?/p>

    原因及解军_法参见:

    http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=81&threadID=8839&messageID=43184#43184



  • Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=579829



    風向逆轉 - p爪哇 2006-03-21 00:27 发表评论
    ]]>
    [收藏]JDBC数据库驱动下载网址大全 (好东西{来分?http://www.tkk7.com/iKingQu/articles/36505.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:57:00 GMThttp://www.tkk7.com/iKingQu/articles/36505.htmlhttp://www.tkk7.com/iKingQu/comments/36505.htmlhttp://www.tkk7.com/iKingQu/articles/36505.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36505.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36505.html链接:http://blog.csdn.net/baggio785/archive/2006/02/07/593802.aspx



    風向逆轉 - p爪哇 2006-03-20 23:57 发表评论
    ]]>
    [收藏]Oracle内存分配与调?http://www.tkk7.com/iKingQu/articles/36492.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:38:00 GMThttp://www.tkk7.com/iKingQu/articles/36492.htmlhttp://www.tkk7.com/iKingQu/comments/36492.htmlhttp://www.tkk7.com/iKingQu/articles/36492.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36492.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36492.html阅读全文

    風向逆轉 - p爪哇 2006-03-20 23:38 发表评论
    ]]>
    [收藏]Oracle基本数据cd存储格式析Q一Q—(五)http://www.tkk7.com/iKingQu/articles/36491.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:37:00 GMThttp://www.tkk7.com/iKingQu/articles/36491.htmlhttp://www.tkk7.com/iKingQu/comments/36491.htmlhttp://www.tkk7.com/iKingQu/articles/36491.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36491.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36491.htmlOracle基本数据cd存储格式析Q一Q——字W类?br />发表?yangtingkun | 发表旉: 2004q十二月09? 23:47
    前一늜完文档,对oracle的基本数据类型的存储格式有了一些了解,最q有做了一些测试进行了验证?br />打算整理ȝ一下,q一主要说明字W类型的存储格式。主要包括char、varchar2和long{几U类型?br /> 
    SQL> create table test_char (char_col char(10), varchar_col varchar2(10), long_col long);
    表已创徏?br />SQL> insert into test_char values ('abc', '123', ',fd');
    已创?1 行?br />SQL> commit;
    提交完成?br />SQL> select rowid from test_char;
    ROWID
    ------------------
    AAAB3LAAFAAAAAgAAA
    Ҏ(gu)rowid的定义规则,W??位是表示的是数据文gQF表示5Q?0?5位表C的是在q个数据文g中的W几个BLOCKQg表示32。(rowid~码相当?4q制。用A~Z a~z 0~9 + /?4个字W表C。A表示0QB表示1Q……,a表示26Q……,0表示52Q……,+表示62Q?表示63。)
    我们Ҏ(gu)计算的结果去dumpq个block?br />SQL> ALTER SYSTEM DUMP DATAFILE 5 BLOCK 32;
    pȝ已更攏V?br />打开产生的trace文gQ?br />data_block_dump,data header at 0x3421064
    ===============
    tsiz: 0x1f98
    hsiz: 0x14
    pbl: 0x03421064
    bdba: 0x01400020
         76543210
    flag=--------
    ntab=1
    nrow=1
    frre=-1
    fsbo=0x14
    fseo=0x1f82
    avsp=0x1f6e
    tosp=0x1f6e
    0xe:pti[0] nrow=1 offs=0
    0x12:pri[0] offs=0x1f82
    block_row_dump:
    tab 0, row 0, @0x1f82
    tl: 22 fb: --H-FL-- lb: 0x1  cc: 3
    col  0: [10]  61 62 63 20 20 20 20 20 20 20
    col  1: [ 3]  31 32 33
    col  2: [ 3]  2c 66 64
    end_of_block_dump
    End dump data blocks tsn: 5 file#: 5 minblk 32 maxblk 32
    观察dump出来的结果,可以发现以下几点Q?br />1.对于每个字段Q除了保存字D늚g外,q会保存当前字段中数据的长度。而且Qoracle昄没有把字D늚长度定义或类型定义保存在block中,q些信息保存在oracle的数据字兔R面?br />2. Ҏ(gu)dump的结果,可以清楚的看刎ͼ字符cd在数据库中是以ascii格式存储的?br />SQL> select chr(to_number('61', 'xx')) from dual;
    CH
    --
    a
    3.charcd为定长格式,存储的时候会在字W串后面填补I格Q而varchar2和longcd都是变长的?br />SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR;
    D_CHAR
    -------------------------------------------------------------
    Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20
    SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR;
    D_VARCHAR2
    -------------------------------------------------------------
    Typ=1 Len=3: 31,32,33
    SQL> SELECT DUMP(LONG_COL, 16) D_VARCHAR2 FROM TEST_CHAR;
    SELECT DUMP(LONG_COL, 16) D_VARCHAR2 FROM TEST_CHAR
                *
    ERROR 位于W?1 ?
    ORA-00997: 非法使用 LONG 数据cd
    ׃DUMP不支持LONGcdQ因此我们用了alter system dump block的方式,通过比较两种方式得到的结果,发现DUMP()函数不但方便Q结果清晎ͼ而且指出了进行DUMP的数据类型,在以后的例子中,除非必要的情况,否则都会采用DUMP()函数的方式进行说明?br />下面看一下插入中文的情况Q首先看一下数据库的字W集
    SQL> select name, value$ from sys.props$ where name like '%CHARACTERSET%';
    NAME                           VALUE$
    ------------------------------ ------------------------------
    NLS_CHARACTERSET               ZHS16GBK
    NLS_NCHAR_CHARACTERSET         AL16UTF16
    SQL> insert into test_char values ('定长', '变长', null);
    已创?1 行?br />SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR;
    D_CHAR
    ----------------------------------------------------------------
    Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20
    Typ=96 Len=10: b6,a8,b3,a4,20,20,20,20,20,20
    SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR;
    D_VARCHAR2
    ----------------------------------------------------------------
    Typ=1 Len=3: 31,32,33
    Typ=1 Len=4: b1,e4,b3,a4
    Ҏ(gu)dumpl果Q可以清楚的看出Q普通英文字W和标点用一个字节表C,而中文字W或中文标点需要两个字节来表示?br />下面Q对比一下nchar和nvarchar2与char、varchar2cd有什么不同?br />SQL> create table test_nchar (nchar_col nchar(10), nvarchar_col nvarchar2(10));
    表已创徏?br />SQL> insert into test_nchar values ('nchar定长', 'nvarchar变长');
    已创?1 行?br />从这里已l可以看Z些不同了Q如果按照刚才中文的计算Ҏ(gu)Q?nvarchar变长'的长度是8+2*2=12已经过了数据类型定义的大小Q可是ؓ什么插入成功了Q?br />q是dump一下看看结果吧?br />SQL> select dump(nchar_col, 16) from test_nchar;
    DUMP(NCHAR_COL,16)
    --------------------------------------------------------------
    Typ=96 Len=20: 0,6e,0,63,0,68,0,61,0,72,5b,9a,95,7f,0,20,0,20,0,20
    SQL> select dump(nvarchar_col, 16) from test_nchar;
    DUMP(NVARCHAR_COL,16)
    --------------------------------------------------------------
    Typ=1 Len=20: 0,6e,0,76,0,61,0,72,0,63,0,68,0,61,0,72,53,d8,95,7f
    q下明白了Q虽然仍然是采用ascii码存储,但是nchar使用的AL16UTF16字符集,~码长度变ؓ2个字节。这样中文用两个字节,对于可以用一个字节就表示的英文字W,采用了高位补0的方式凑?位,q样Q对于采用AL16UTF16字符集的ncharcdQ无Z文还是英文都?位字W表C。因?nvarchar变长'的长度是10Qƈ没有过数据cd的限制?br />==============================================================
    Oracle基本数据cd存储格式析Q二Q——数字类?br />发表?yangtingkun | 发表旉: 2004q十二月14? 22:57
    q篇文章主要描述NUMBERcd的数据和如何在数据库中存储的?br />Oracle的NUMBERcd最多由三个部分构成Q这三个部分分别是最高位表示位、数据部分、符号位。其中负数包含符号位Q正C会包括符号位。另外,数?比较Ҏ(gu)Q它只包含一个数值最高位表示?0Q没有数据部分?br />正数的最高位表示位大?0Q负数的最高位表示位小?0。其中一个正数的最高位是个位的话,则最高位表示位ؓC1Q百位、万位依ơؓC2、C3Q百分位、万分ؓ依次为C0、BF。一个负数的最高位Z位的话,最高位表示位ؓ3EQ百位、万位依ơؓ3D?CQ百分位、万分位依次?F?0?br />数据部分每一位都表示2位数。这个两位数可能是从0?9Q如果是数据本n是正敎ͼ则分别用二进制的1?4表示Q如果数据本w是负数Q则使用二进?5?表示?br />W号位用66表示?br />上面的这些是我通过DUMPl果ȝ出来的,对于上面提到的这些关pd敎ͼOracle之所以这样选择是有道理的,我们后面Ҏ(gu)例子也可以推导出来,而且会进一步说明ؓ什么会采用q种方式表示。这里列出的意思是使大家先对NUMBERcd数据有一个大概的了解?br />下面我们通过一个例子详l说明:
     
    SQL> CREATE TABLE TEST_NUMBER (NUMBER_COL NUMBER);
    表已创徏?br />SQL> INSERT INTO TEST_NUMBER VALUES (0);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (1);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (2);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (25);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (123);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (4100);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (132004078);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (2.01);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (0.3);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (0.00000125);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (115.200003);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (-1);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (-5);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (-20032);
    已创?1 行?br />SQL> INSERT INTO TEST_NUMBER VALUES (-234.432);
    已创?1 行?br />SQL> COMMIT;
    提交完成?br />SQL> COL D_NUMBER FORMAT A50
    SQL> SELECT NUMBER_COL, DUMP(NUMBER_COL, 16) D_NUMBER FROM TEST_NUMBER;
    NUMBER_COL D_NUMBER
    ---------- --------------------------------------------------
             0 Typ=2 Len=1: 80
             1 Typ=2 Len=2: c1,2
             2 Typ=2 Len=2: c1,3
            25 Typ=2 Len=2: c1,1a
           123 Typ=2 Len=3: c2,2,18
          4100 Typ=2 Len=2: c2,2a
     132004078 Typ=2 Len=6: c5,2,21,1,29,4f
          2.01 Typ=2 Len=3: c1,3,2
            .3 Typ=2 Len=2: c0,1f
     .00000125 Typ=2 Len=3: be,2,1a
    115.200003 Typ=2 Len=6: c2,2,10,15,1,4
            -1 Typ=2 Len=3: 3e,64,66
            -5 Typ=2 Len=3: 3e,60,66
        -20032 Typ=2 Len=5: 3c,63,65,45,66
      -234.432 Typ=2 Len=6: 3d,63,43,3a,51,66
    已选择15行?br /> 
        下面Ҏ(gu)例子得到的结果,Ҏ(gu)行进行说明。首先说明两点基本的。DUMP函数q回的TYPEQ?表示DUMP的数据类型是NUMBERQLENGTHQN表示数值在数据库中存储的长度是N?br />1.DUMP(0)的结果是0x80Q在前面已经提到Q?只有高位表示位,没有数据位。由?的特D,既不属于正数Q也不属于负敎ͼ因此使用高位表示位用80表示p够了Q不会和其它数据冲突QOracleZ节省I间的考虑后面数据部分省掉了。但是ؓ什么Oracle选择0x80表示0呢?我们知道正数和负C为相反数Q每个正数都有一个对应的负数。因此如果我们要使用~码表示数|则表C正数和负数的编码应该各占一半,q样才能保证使Oracle表示数据范围是合理的。?x80的二q制~码?000 0000Q正好是一个字节编码最大值的一半,因此QOracle选择0x80来表C?Q是十分有道理的?br />2.DUMP(1)的结果是0xc102Q?xc1表示了最高位个位Q?x2表示数值是1。首先,OracleZ么用C1表示个位呢?其实Q道理和刚才的差不多。采用科学计数法QQ何一个实数S都可以描qCؓA.B×10nQA表示整数部分QB表示数部分Q而N表示10的指数部分。当S大于1ӞN大于{于0QS于1ӞN于0。也是_采用指数的方式表C,N大于0和N于0的情况各占一半左xQOracle所表示的范围最qѝ因此,Oracle选择了C1表示个位是最高位的情c?br />SQL> SELECT TO_CHAR(ROUND(TO_NUMBER('81', 'XXX') + (TO_NUMBER('FF', 'XXX') - TO_NUMBER('81', 'XXX') + 1)/2), 'XX') FROM DUAL;
    TO_
    ---
     C1
     
    Z么ORACLE使用0x2表示1Q而不直接使用0x1表示1呢?Oracle每个字节表示2位数Q因此对于这?位数Q出现的可能??9?00U可能,问题出在0q里。Oracle底层是用C语言实现的,我们知道二进?在C语言中用作字W串l结W,OracleZ避免q个问题Q因此用了0x1表示0Qƈ依次cLQ?x64表示99?br />3.DUMP(2)的结果是0xc103?br />4.DUMP(25)的结果是0xc11a。前面提刎ͼ数据部分是以2位ؓ最单位保存的。因此对?5来说Q最高位表示位仍然是个位Q个位上的值是25Q根据上面推出的规则Q?5在存储ؓ0xc11a?br />SQL> SELECT TO_CHAR(25 + 1, 'xx') FROM DUAL;
    TO_
    ---
     1a
     
    5.DUMP(123)的结果是0xc20218。由?23最高ؓ是百位,所以最高位表示位ؓ0xc2Q百位上?Q用0x02表示Q个位上?3Q用0x18表示?br />6.DUMP(4100)的结果是0xc22a?br />注意一点,如果数字最后数位上如果?QOracleZ节省I间的考虑不会存储。比如:4100只保存百位上?1Q?2000000只保存百位位上的12Q?12000只保存万位上?1和百位上?0?br />7.DUMP(132004078)的结果是0xc5022101294f。最高位是亿位,因此?xC5表示Q亿位上??x02表示Q百位位上是32?x21表示Q万位上??x01表示Q百位上?0?x29表示Q个位上78?x4F表示?br />注意Q中间数位上?不能省略?br />8.DUMP(2.01)的结果是0xc10302。最高位是个位用0xC1表示Q个位上??x03表示Q百分位上是1?x02表示?br />注意Q个位下面一位是癑ֈ位不是十分位?br />9.DUMP(0.3)的结果是0xc01f。最高位是百分位Q?xC0表示Q百分位上是30?x1F表示?br />10.DUMP(0.00000125)的结果是0xbe021a。最高位是百万分位,?xBE表示Q最高位上的1?x02表示Q?5?x1a表示?br />11.DUMP(115.200003)的结果是0xc20210150104?br />12.DUMP(-1)的结果是0x3e6466。最高位个位Q用0x3E表示Q?4表示个位上是1Q?6是符号位Q表C个数是负数?br />负数和正C为相反数Q负数的最高位表示位和它对应的相反数的最高位相加的值是FF?的最高位表示位是C1Q?1的最高位表示位是3E。负C1?4表示。负C的数值和它相反数的数据相加是0x66Q也是W号位。正??x02表示Q负??x64表示Q二者相加是0x66。负数多个一个标识位Q用0x66表示。由于正数的表示范围?x01?x64Q负数的表示范围?x65?x02。因此,不会在表C数字时出现?x66表示?br />13.DUMP(-5)的结果是0x3e6066?x3e表示最高位是个位,0x60表示个位上是5Q?x66是符h识位?x3E?xC1?xFF?x60?x06的结果是0x66?br />14.DUMP(-20032)的结果是0x3c63654566。最高位是万位,正数的万位是0xC3Q因此负数的万位?x3C。万位上?Q正数用0x03表示Q负Cؓ0x63Q百位上?Q正数用0x01表示Q负C?x65表示Q个位上?2Q正数用0x21表示Q负C?x45表示?x66是负数表CZ?br />15.DUMP(-234.432)的结果是0x3d63433a5166?br /> 
    Ҏ(gu)Oracle的存储特性,q可以推出Oracle的numbercd的取D围?br />Oracle的concept上是q样描述的:
    The following numbers can be stored in a NUMBER column:
    Positive numbers in the range 1 x 10-130 to 9.99...9 x 10125 with up to 38 significant digits.
    Negative numbers from -1 x 10-130 to 9.99...99 x 10125 with up to 38 significant digits.
    Zero.
    下面来推导出取D围?br />来看W号位,0xC1表示个位?br />SQL> select to_number('ff', 'xxx') - to_number('c1', 'xxx') from dual;
    TO_NUMBER('FF','XXX')-TO_NUMBER('C1','XXX')
    -------------------------------------------
                                             62
    ׃Oracle是两位、两位存储的Q因此最高位相当?2×2=124Q而且最高位上最大值是99Q因此正数的最大gؓ9.999……?0125?br />SQL> select to_number('c1', 'xxx') - to_number('80', 'xxx') from dual;
    TO_NUMBER('C1','XXX')-TO_NUMBER('80','XXX')
    -------------------------------------------
                                             65
    最高位相当?5×2=130Q因此正数的最gؓ1×10-130?br />负数和正数在各用了一半的~码Q因此具有相同的极D围?br />==============================================================
    Oracle基本数据cd存储格式析Q三Q——日期类型(一Q?br />发表?yangtingkun | 发表旉: 2004q十二月15? 14:00
    q篇文章描述DATEcd的数据在Oracle中是以何U格式存攄?
    下面通过一个例子进行说明?
     
    SQL> create table test_date (date_col date);
    表已创徏?br />SQL> insert into test_date values (to_date('2000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (to_date('1-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (to_date('-1-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (to_date('-101-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (to_date('-4712-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (to_date('9999-12-31 23:59:59', 'syyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> insert into test_date values (sysdate);
    已创?1 行?br />SQL> insert into test_date values (to_date('-4713-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));
    insert into test_date values (to_date('-4713-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'))
                                          *
    ERROR 位于W?1 ?
    ORA-01841: Q全Q年度值必M?-4713 ?+9999 之间Q且不ؓ 0
    SQL> insert into test_date values (to_date('0000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));
    insert into test_date values (to_date('0000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'))
                                          *
    ERROR 位于W?1 ?
    ORA-01841: Q全Q年度值必M?-4713 ?+9999 之间Q且不ؓ 0
    SQL> col dump_date format a80
    SQL> select to_char(date_col, 'syyyy-mm-dd hh24:mi:ss'), dump(date_col) dump_date from test_date;
    TO_CHAR(DATE_COL,'SY DUMP_DATE
    -------------------- ---------------------------------------
     2000-01-01 00:00:00 Typ=12 Len=7: 120,100,1,1,1,1,1
     0001-01-01 00:00:00 Typ=12 Len=7: 100,101,1,1,1,1,1
    -0001-01-01 00:00:00 Typ=12 Len=7: 100,99,1,1,1,1,1
    -0101-01-01 00:00:00 Typ=12 Len=7: 99,99,1,1,1,1,1
    -4712-01-01 00:00:00 Typ=12 Len=7: 53,88,1,1,1,1,1
     9999-12-31 23:59:59 Typ=12 Len=7: 199,199,12,31,24,60,60
     2004-12-15 13:56:19 Typ=12 Len=7: 120,104,12,15,14,57,20
    已选择7行?br /> 
    通过最后两条语句已l可以看出Oracle的DATEcd的取D围是公元?712q??日至公元9999q?2?1日。而且Ҏ(gu)日期的特定,要不然是公元1q_要不然是公元?q_不会出现0q的情况?br />日期cd长度?Q?个字节分别表CZU、年、月、日、时、分和秒?br />׃不会出现0的情况,月和日都是按照原值存储的Q月的范围是1?2Q日的范围是1?1?br />׃时、分、秒都会出现0的情况,因此存储旉用原值加1的方式?时保存ؓ1Q?3时保存ؓ14Q?3时保存ؓ24。分和秒的情况与时cM。小时的范围??3Q在数据库中??4保存。分和秒的范围都??9Q在数据库中??0保存?br />q和世纪的情늛Ҏ(gu)较复杂,可分为公元前和公元后两种情况。由于最的世纪的值是-47Q公元前4712q_Q最大值是99Q公?999q_。ؓ了避免负数的产生Qoracle把世U加100保存在数据库中。公?000q_世纪保存?20Q公?999q_世纪保存?99Q公元前101q_世纪保存?9Q?00+(-1)Q,公元?712q_世纪保存?3Q?00+(-47)Q?br />注意Q对于公元前1q_虽然已经是公元前了,但是表示世纪的前两位的g然是0Q因此,q时的保存的世纪的g然是100。世U的范围?47?9Q保存的值是53?99?br />q的保存与世U的保存方式cMQ也把年的值加?00q行保存。对于公?000q_q保持ؓ100Q公?q保存ؓ101Q公?004q保存ؓ104Q公?999q保存ؓ199Q公元前1q_保存?9Q?00+(-1)Q,公元?01q_保存?9Q?00+(-1)Q,公元?712q保存ؓ88Q?00+(-12)Q。对于公元前的年Q保存的值L于{于100Q对于公元后的年Q保存的值L大于{于100。年的范围是0?9Q保存的值是1?99?br />注意Q一般的世纪Q都包含?00q_而对?世纪Q由于包含公元前和公元后两部分且不包?q_因此包含?98q?br />==============================================================
    Oracle基本数据cd存储格式析Q三Q——日期类型(二)
    发表?yangtingkun | 发表旉: 2004q十二月16? 18:03
    q篇文章描述TIMESTAMPcd的数据在Oracle中是以何U格式存攄?br />下面通过一个例子进行说明?br /> 
    SQL> create table test_time (col_time timestamp);
    表已创徏?br />SQL> insert into test_time values (to_timestamp('0001-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
    已创?1 行?br />SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
    已创?1 行?br />SQL> insert into test_time values (to_timestamp('9999-12-31 23:59:59.999999', 'syyyy-mm-dd hh24:mi:ss.ff'));
    已创?1 行?br />SQL> insert into test_time values (to_timestamp('-0001-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
    已创?1 行?br />SQL> insert into test_time values (to_timestamp('-0100-3-4 13:2:3.234015', 'syyyy-mm-dd hh24:mi:ss.ff'));
    已创?1 行?br />SQL> insert into test_time values (systimestamp);
    已创?1 行?br />SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.123456789', 'syyyy-mm-dd hh24:mi:ss.ff9'));
    已创?1 行?br />SQL> commit;
    提交完成?br />SQL> select to_char(col_time, 'syyyy-mm-dd hh24:mi:ss.ff9') time, dump(col_time) dump_time
      2  from test_time;
    TIME                           DUMP_TIME
    ------------------------------ ----------------------------------------------------
     0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,101,1,1,1,1,1
     2000-01-01 00:00:00.000000000 Typ=180 Len=7: 120,100,1,1,1,1,1
     9999-12-31 23:59:59.999999000 Typ=180 Len=11: 199,199,12,31,24,60,60,59,154,198,24
    -0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,99,1,1,1,1,1
    -0100-03-04 13:02:03.234015000 Typ=180 Len=11: 99,100,3,4,14,3,4,13,242,201,24
     2004-12-15 16:14:52.738000000 Typ=180 Len=11: 120,104,12,15,17,15,53,43,252,252,128
     2000-01-01 00:00:00.123457000 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,232
    已选择7行?br />与DATEcdҎ(gu)可以发现Q对于TIMESTAMPcdQ如果不包含微秒信息或者微Ugؓ0Q那么存储结果和DATE完全相同。当微秒gؓ0ӞOracleZ节省I间Q不会保存微U信息?br />如果毫秒g?QOracle把微U值当作一?位数的数字来保存?br />比如999999000Q保存ؓ59,154,198,24?34015000保存?3,242,201,24?br />SQL> select to_char(999999000, 'xxxxxxxxxx') from dual;
    TO_CHAR(999
    -----------
       3b9ac618
    SQL> select to_number('3b', 'xxx') one, to_number('9a', 'xxx') two,
      2  to_number('c6', 'xxx') three, to_number('18', 'xxx') four from dual;
           ONE        TWO      THREE       FOUR
    ---------- ---------- ---------- ----------
            59        154        198         24
    SQL> select to_char(234015000, 'xxxxxxxx') from dual;
    TO_CHAR(2
    ---------
      df2c918
    SQL> select to_number('d', 'xxx') one, to_number('f2', 'xxx') two,
      2  to_number('c9', 'xxx') three, to_number('18', 'xxx') four from dual;
           ONE        TWO      THREE       FOUR
    ---------- ---------- ---------- ----------
            13        242        201         24
     
    另外Q注意一点,不指定精度的情况下,TIMESTAMP默认?位。长度超q?位,会四舍五入到6位。如果希望保?位的TIMESTAMPQ必L指定精度?br />SQL> alter table test_time modify (col_time timestamp(9));
    表已更改?br />SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.123456789', 'syyyy-mm-dd hh24:mi:ss.ff9'));
    已创?1 行?br />SQL> select to_char(col_time, 'syyyy-mm-dd hh24:mi:ss.ff9') time, dump(col_time) dump_time
      2  from test_time;
    TIME                           DUMP_TIME
    ------------------------------ ---------------------------------------------------
     0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,101,1,1,1,1,1
     2000-01-01 00:00:00.000000000 Typ=180 Len=7: 120,100,1,1,1,1,1
     9999-12-31 23:59:59.999999000 Typ=180 Len=11: 199,199,12,31,24,60,60,59,154,198,24
    -0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,99,1,1,1,1,1
    -0100-03-04 13:02:03.234015000 Typ=180 Len=11: 99,100,3,4,14,3,4,13,242,201,24
     2004-12-15 16:14:52.738000000 Typ=180 Len=11: 120,104,12,15,17,15,53,43,252,252,128
     2000-01-01 00:00:00.123457000 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,232
     2000-01-01 00:00:00.123456789 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,21
    已选择8行?br />==============================================================
    Oracle基本数据cd存储格式析Q三Q——日期类型(三)
    发表?yangtingkun | 发表旉: 2004q十二月17? 17:00
    如果直接在SQL语句中对SYSDATE或由TO_DATE函数生成日期q行DUMP操作Q会发现得到的结果与DUMP数据库中保存的日期的l果不一栗?br /> 
    SQL> truncate table test_date;
    表已截掉?br />SQL> insert into test_date values (to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'));
    已创?1 行?br />SQL> col dump_date format a65
    SQL> select to_char(date_col, 'syyyy-mm-dd hh24:mi:ss') dat, dump(date_col) dump_date from test_date;
    DAT                  DUMP_DATE
    -------------------- ---------------------------------------------------------
     2004-12-17 16:42:42 Typ=12 Len=7: 120,104,12,17,17,43,43
    SQL> select to_char(to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'), 'syyyy-mm-dd hh24:mi:ss') dat,
      2  dump(to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss')) dump_date from dual;
    DAT                  DUMP_DATE
    -------------------- ---------------------------------------------------------
     2004-12-17 16:42:42 Typ=13 Len=8: 212,7,12,17,16,42,42,0
    存储在数据库中的DATEcd?2Q而直接在SQL中用的DATEcd?3。而且二者的长度以及表示方式都不相同。这两种cd的不同指Z要体现在两点Q一Q时、分、秒的表CZ同;二、世U和q的表示不同?br />SQL中用DATE的时分秒没有采用?存储方式Q而且原值存储?br />SQL中用DATE没有采用世纪、年的方式保持,而是采用了按数g存的方式。第一位表CZ位,W二位表C高位。低位表C最大的值是255。如上面的例子中Q?12+7×256=2004?br />SQL> select to_char(to_date('-2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'), 'syyyy-mm-dd hh24:mi:ss') dat,
      2  dump(to_date('-2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss')) dump_date from dual;
    DAT                  DUMP_DATE
    -------------------- ---------------------------------------------------
    -2004-12-17 16:42:42 Typ=13 Len=8: 44,248,12,17,16,42,42,0
    SQL> select dump(to_date('-1-1-1', 'syyyy-mm-dd')) from dual;
    DUMP(TO_DATE('-1-1-1','SYYYY-MM-D
    ---------------------------------
    Typ=13 Len=8: 255,255,1,1,0,0,0,0
     
    对于公元前的日期QOracle?55Q?55开始保存。公元前的年的保存的值和对应的公元后的年的值相加的和是256Q?55。如上例中的公元2004q和公元?004q的值相加:212+44=256Q?+248=255?br />SQL中DATEcd最后还包括一?Q似乎目前没有用?br />==============================================================
    Oracle基本数据cd存储格式析Q三Q——日期类型(四)
    发表?yangtingkun | 发表旉: 2005q一?2? 02:26
    本文对TIMESTAMP WITH LOCAL TIME ZONE和TIMESTAMP WITH TIME ZONEcd的存储格式进行简单的说明?br /> 
    SQL> CREATE TABLE TEST_TIMESTAMP(TIME1 TIMESTAMP(9), TIME2 TIMESTAMP(6) WITH LOCAL TIME ZONE,
      2  TIME3 TIMESTAMP(4) WITH TIME ZONE);
    表已创徏?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    SQL> SELECT * FROM TEST_TIMESTAMP;
    TIME1
    ----------------------------------------------------
    TIME2
    ----------------------------------------------------
    TIME3
    ----------------------------------------------------
    11-1?-05 11.08.15.027000000 下午
    11-1?-05 11.08.15.027000 下午
    11-1?-05 11.08.15.0270 下午 +08:00
    SQL> SELECT DUMP(TIME1, 16), DUMP(TIME2, 16), DUMP(TIME3, 16) FROM TEST_TIMESTAMP;
    DUMP(TIME1,16)
    -------------------------------------------------------------
    DUMP(TIME2,16)
    -------------------------------------------------------------
    DUMP(TIME3,16)
    -------------------------------------------------------------
    Typ=180 Len=11: 78,69,1,b,18,9,10,1,9b,fc,c0
    Typ=231 Len=11: 78,69,1,b,18,9,10,1,9b,fc,c0
    Typ=181 Len=13: 78,69,1,b,10,9,10,1,9b,fc,c0,1c,3c
    可以发现Q如果客L和数据库中的时区是一致的Q那么TIMESTAMP和TIMESTAMP WITH LOCAL TIME ZONE存储的数据是完全一L?
    TIMESTAMP WITH TIME ZONE则略有不同,它保存的?时区的时_和所处的时区信息?
    修改客户端主机的时区Q由?区(+8区)改ؓ0时区?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    修改客户端主机的时区Q改5区(-5时区Q?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    修改客户端主机的时区Q改12区(-12时区Q?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    修改客户端主机的时区Q改Z13区(+13时区Q?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    修改客户端主机的时区Q改3.5区(-3.5时区Q?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    修改客户端主机的时区Q改Z9.5区(+9.5时区Q?
    SQL> INSERT INTO TEST_TIMESTAMP VALUES (SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
    已创?1 行?
    SQL> COMMIT;
    提交完成?
    修改客户端主机的时区Q改回东8区(+8时区Q?
    SQL> SELECT * FROM TEST_TIMESTAMP;
    TIME1
    -----------------------------------------------
    TIME2
    -----------------------------------------------
    TIME3
    -----------------------------------------------
    11-1?-05 11.08.15.027000000 下午
    11-1?-05 11.08.15.027000 下午
    11-1?-05 11.08.15.0270 下午 +08:00
    11-1?-05 03.11.43.746000000 下午
    11-1?-05 11.11.43.746000 下午
    11-1?-05 03.11.43.7460 下午 +00:00
    11-1?-05 10.14.08.987000000 上午
    11-1?-05 11.14.08.987000 下午
    11-1?-05 10.14.08.9870 上午 -05:00
    11-1?-05 03.15.01.732000000 上午
    11-1?-05 11.15.01.732000 下午
    11-1?-05 03.15.01.7320 上午 -12:00
    12-1?-05 04.20.21.522000000 上午
    11-1?-05 11.20.21.522000 下午
    12-1?-05 04.20.21.5220 上午 +13:00
    11-1?-05 02.15.16.567000000 下午
    12-1?-05 01.45.16.567000 上午
    11-1?-05 02.15.16.5670 下午 -03:30
    12-1?-05 03.16.54.992000000 上午
    12-1?-05 01.46.54.992000 上午
    12-1?-05 03.16.54.9920 上午 +09:30
    已选择7行?
    SQL> SELECT DUMP(TIME1, 16), DUMP(TIME2, 16), DUMP(TIME3, 16) FROM TEST_TIMESTAMP;
    DUMP(TIME1,16)
    -------------------------------------------------------------
    DUMP(TIME2,16)
    -------------------------------------------------------------
    DUMP(TIME3,16)
    -------------------------------------------------------------
    Typ=180 Len=11: 78,69,1,b,18,9,10,1,9b,fc,c0
    Typ=231 Len=11: 78,69,1,b,18,9,10,1,9b,fc,c0
    Typ=181 Len=13: 78,69,1,b,10,9,10,1,9b,fc,c0,1c,3c
    Typ=180 Len=11: 78,69,1,b,10,c,2c,2c,77,e,80
    Typ=231 Len=11: 78,69,1,b,18,c,2c,2c,77,e,80
    Typ=181 Len=13: 78,69,1,b,10,c,2c,2c,77,e,80,14,3c
    Typ=180 Len=11: 78,69,1,b,b,f,9,3a,d4,6c,c0
    Typ=231 Len=11: 78,69,1,b,18,f,9,3a,d4,6c,c0
    Typ=181 Len=13: 78,69,1,b,10,f,9,3a,d4,6c,c0,f,3c
    Typ=180 Len=11: 78,69,1,b,4,10,2,2b,a1,6f,0
    Typ=231 Len=11: 78,69,1,b,18,10,2,2b,a1,6f,0
    Typ=181 Len=13: 78,69,1,b,10,10,2,2b,a1,6f,0,8,3c
    Typ=180 Len=11: 78,69,1,c,5,15,16,1f,1d,16,80
    Typ=231 Len=11: 78,69,1,b,18,15,16,1f,1d,16,80
    Typ=181 Len=13: 78,69,1,b,10,15,16,1f,1d,16,80,21,3c
    Typ=180 Len=11: 78,69,1,b,f,10,11,21,cb,bb,c0
    Typ=231 Len=11: 78,69,1,c,2,2e,11,21,cb,bb,c0
    Typ=181 Len=13: 78,69,1,b,12,2e,11,21,cb,bb,c0,11,1e
    Typ=180 Len=11: 78,69,1,c,4,11,37,3b,20,b8,0
    Typ=231 Len=11: 78,69,1,c,2,2f,37,3b,20,b8,0
    Typ=181 Len=13: 78,69,1,b,12,2f,37,3b,20,b8,0,1d,5a
     
    SQL> SELECT TO_NUMBER('1C', 'XXX'), TO_NUMBER('3C', 'XXX') FROM DUAL;
    TO_NUMBER('1C','XXX') TO_NUMBER('3C','XXX')
    --------------------- ---------------------
                       28                    60
    SQL> SELECT TO_NUMBER('14', 'XXX'), TO_NUMBER('3C', 'XXX'), TO_NUMBER('143C', 'XXXXXXX') FROM DUAL;
    TO_NUMBER('14','XXX') TO_NUMBER('3C','XXX')
    --------------------- ---------------------
                       20                    60
    SQL> SELECT TO_NUMBER('3C', 'XXX') , TO_NUMBER('1E', 'XXX'), TO_NUMBER('5A', 'XXX') FROM DUAL;
    TO_NUMBER('3C','XXX') TO_NUMBER('1E','XXX') TO_NUMBER('5A','XXX')
    --------------------- --------------------- -------------------
                       60                    30                  90
    可以看出Q修Ҏ(gu)ZDpȝTIMESTAMP旉发生变化Q但是对于TIMESTAMP WITH LOCAL TIME ZONEcdQL系l的旉转化到数据库服务器上时区的时间进行存储?
    TIMESTAMP WITH TIME ZONE保存的是当前旉转化?时区的对应的旉Qƈ通过最后两位来保存时区信息?
    W一位表C时区的时部分?时区?x14表示。东n区在q个基础上加nQ西n区在q个基础上减n。我们所处的?CZؓ0x1C。西5CZؓ0xF?
    W二位表C时区的分钟部分。标准是0x3CQ即60分钟。对于东时区的半区,在这个基上加?0分钟Q如果是西时区,则减?0分钟?br />==============================================================
    Oracle基本数据cd存储格式析Q四Q——ROWIDcdQ一Q?br />发表?yangtingkun | 发表旉: 2004q十二月21? 19:14
    Oracle的ROWID用来唯一标识表中的一条记录,是这条数据在数据库中存放的物理地址?br />Oracle的ROWID分ؓ两种Q物理ROWID和逻辑ROWID。烦引组l表使用逻辑ROWIDQ其他类型的表用物理ROWID。其中物理ROWID在Oracle?版本中进行了扩展QOracle7及以下版本用约束ROWIDQOracle8及以上版本用扩展ROWID。本文描q物理扩展ROWIDQ由于约束ROWID仅仅是ؓ了兼Ҏ(gu)期版本,因此不做讨论?br />SQL> create table test_rowid (id number, row_id rowid);
    表已创徏?br />SQL> insert into test_rowid values (1, null);
    已创?1 行?br />SQL> update test_rowid set row_id = rowid where id = 1;
    已更?1 行?br />SQL> commit;
    提交完成?br />SQL> select rowid, row_id from test_rowid;
    ROWID              ROW_ID
    ------------------ ------------------
    AAABnRAAGAAAACWAAA AAABnRAAGAAAACWAAA
    Oracle的物理扩展ROWID?8位,每位采用64位编码,分别用A~Z、a~z?~9???4个字W表C。A表示0QB表示1Q……Z表示25Qa表示26Q……z表示51Q?表示52Q……,9表示61Q?表示62Q?表示63?br />ROWID具体划分可以分ؓ4部分?br />1.OOOOOOQ前6位表CDATA OBJECT NUMBERQ将赯{化位数字后匹配DBA_OBJECTS中的DATA_OBJECT_IDQ可以确定表信息?br />如上面例子中的DATA OBJECT NUMBER是AAABnRQ{化位数字?×64×64 Q?9×64 Q?17?br />SQL> select owner, object_name from dba_objects
      2  where data_object_id = 1*64*64 + 39*64 + 17;
    OWNER                          OBJECT_NAME
    ------------------------------ -----------------------------
    YANGTK                         TEST_ROWID
    2.FFFQ第7?位表C相对表I间的数据文件号?br />上面的例子中是AAGQ表C数据文??br />SQL> select file_name, tablespace_name from dba_data_files where relative_fno = 6;
    FILE_NAME                                     TABLESPACE_NAME
    --------------------------------------------- ---------------
    E:ORACLEORADATATESTYANGTK01.DBF           YANGTK
    3.BBBBBBQ第10?5位表C条记录在数据文g中的W几个BLOCK中?br />上面的例子是AAAACWQ{化位数字?×64Q?2Q表C条记录在数据文g中的W?50个BLOCK?br />4.RRRQ最?位表C条记录是BLOCK中的W几条记录?br />上面的例子是AAAQ表C第0条记录(L?开始计敎ͼ?br />SQL> alter system dump datafile 6 block 150;
    pȝ已更攏V?br />SQL> select row_id, dump(row_id, 16) dump_rowid from test_rowid;
    ROW_ID             DUMP_ROWID
    ------------------ -------------------------------------------------
    AAABnRAAGAAAACWAAA Typ=69 Len=10: 0,0,19,d1,1,80,0,96,0,0
     
    扑ֈ对应的dump文gQ可以发现类型的信息
    *** 2004-12-21 17:58:26.000
    *** SESSION ID:(13.91) 2004-12-21 17:58:26.000
    Start dump data blocks tsn: 6 file#: 6 minblk 150 maxblk 150
    buffer tsn: 6 rdba: 0x01800096 (6/150)
    scn: 0x0000.2e389c16 seq: 0x01 flg: 0x06 tail: 0x9c160601
    frmt: 0x02 chkval: 0xc97d type: 0x06=trans data
    Block header dump:  0x01800096
     Object id on Block? Y
     seg/obj: 0x19d1  csc: 0x00.2e389c0f  itc: 2  flg: O  typ: 1 - DATA
         fsl: 0  fnx: 0x0 ver: 0x01
     
     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0003.009.00000057  0x0080004b.0042.56  --U-    1  fsc 0x0000.2e389c16
    0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
     
    data_block_dump,data header at 0x651105c
    ===============
    tsiz: 0x3fa0
    hsiz: 0x14
    pbl: 0x0651105c
    bdba: 0x01800096
         76543210
    flag=--------
    ntab=1
    nrow=1
    frre=-1
    fsbo=0x14
    fseo=0x3f89
    avsp=0x3f7b
    tosp=0x3f7b
    0xe:pti[0] nrow=1 offs=0
    0x12:pri[0] offs=0x3f89
    block_row_dump:
    tab 0, row 0, @0x3f89
    tl: 17 fb: --H-FL-- lb: 0x1  cc: 2
    col  0: [ 2]  c1 02
    col  1: [10]  00 00 19 d1 01 80 00 96 00 00
    end_of_block_dump
    End dump data blocks tsn: 6 file#: 6 minblk 150 maxblk 150
     
    有时需要查看表的DUMP信息Q但是很隑և定位表中数据开始于哪个BLOCKQ根据ROWID中包含的信息可以方便的扑ֈ起始BLOCK?br />下面单描qC下ROWIDcd是如何存储的?br />SQL> select row_id, dump(row_id, 16) dump_rowid from test_rowid;
    ROW_ID             DUMP_ROWID
    ------------------ -------------------------------------------------
    AAABnRAAGAAAACWAAA Typ=69 Len=10: 0,0,19,d1,1,80,0,96,0,0
    ?位表CROWID的前6位,也就是DATA_OBJECT_ID信息。数据以数值的格式保存?br />SQL> select to_number('19d1', 'xxxxxx') from dual;
    TO_NUMBER('19D1','XXXXXX')
    --------------------------
                          6609
    SQL> select 1*64*64 + 39*64 + 17 from dual;
    1*64*64+39*64+17
    ----------------
                6609
    q里存在一个问题,Ҏ(gu)ROWID的取D_OBJECT_DATA_ID最大的值是64?ơ方Q而根据DUMPQoracle只用?位保存,因此取D围是256?ơ方?br />SQL> set numwid 12
    SQL> select power(64, 6), power(256, 4), power(64, 6)/power(256, 4) from dual;
     POWER(64,6) POWER(256,4) POWER(64,6)/POWER(256,4)
    ------------ ------------ ------------------------
     68719476736   4294967296                       16
    可见QOBJECT_DATA_ID的最大值是4294967296Q当过q个值时会出现重复的情况。(当然Q现实中不大可能Q?br />后面4位比较特D,是数据文件号和BLOCK数的“和”值构成?br />数据文g的数g64后保存在5?位上?br />SQL> select to_number('0180', 'xxxx') from dual;
    TO_NUMBER('0180','XXXX')
    ------------------------
                         384
    SQL> select 6*64 from dual;
            6*64
    ------------
             384
    同时Q?位BLOCK的|也保存在q?位上Qƈ与数据文件{存结果相加。仍然是以数字格式存放?br />SQL> select to_number('96', 'xxx') from dual;
    TO_NUMBER('96','XXX')
    ---------------------
                      150
    SQL> select 2*64 + 22 from dual;
       2*64+22
    ----------
           150
    ׃采用两位保存数据文g的|且最单位是64Q因此,ROWID中可以保存的数据文g数是1024Q超q?024会造成ROWID的重复?br />SQL> select 256*256/64 from dual;
    256*256/64
    ----------
          1024
    ׃BLOCK的值和数据文gqq?位,因此BLOCK的第3位最大值应于64Q这h能保证ROWID的不重复。因此BLOCK值的最大值应该是4194304?br />SQL> select 64*256*256 from dual;
    64*256*256
    ----------
       4194304
    最后两位保存BLOCK中记录的倹{这个值的最大值是65536?br />SQL> select 256*256 from dual;
       256*256
    ----------
         65536
     
    下面看一个例子,Oracle是如何将相对文g号和BLOCK号“共享”第5?字节的?br />SQL> select blocks from user_segments where segment_name = 'TEST1';
        BLOCKS
    ----------
         86016
    SQL> select max(rowid), dump(max(rowid)) dump_rowid from test1;
    MAX(ROWID)         DUMP_ROWID
    ------------------ -------------------------------------------
    AAABy+AAJAAAU5EAAM Typ=69 Len=10: 0,0,28,190,2,65,78,68,0,12
    SQL> select dbms_rowid.rowid_relative_fno('AAABy+AAJAAAU5EAAM') fno,
      2  dbms_rowid.rowid_block_number('AAABy+AAJAAAU5EAAM') block_num from dual;
           FNO  BLOCK_NUM
    ---------- ----------
             9      85572
    SQL> select 9*64, 2*256+65 from dual;
          9*64   2*256+65
    ---------- ----------
           576        577
    SQL> select 1*256*256 + 78*256 + 68 from dual;
    1*256*256+78*256+68
    -------------------
                  85572
    可以看到Q??为的值除?4得到的商是相Ҏ(gu)件号Q余数是BLOCKL高位Q乘?5536后加上低两位才是BLOCK受?br />==============================================================
    Oracle基本数据cd存储格式析Q四Q——ROWIDcdQ二Q?br />发表?yangtingkun | 发表旉: 2004q十二月22? 23:52
    Oracle的文档上没有介绍逻辑ROWID的编码规则,而且通过DUMP的结果也很难反推出编码规则。因此,本文只简单讨Z下逻辑ROWID的存储?br />下面来看例子?br />SQL> create table test_index (id number primary key, name varchar2(20)) organization index;
    表已创徏?
    SQL> insert into test_index values (1, 'a');
    已创?1 行?
    SQL> commit;
    提交完成?
    SQL> col dump_rowid format a60
    SQL> select rowid, dump(rowid) dump_rowid from test_index;
    ROWID                       DUMP_ROWID
    --------------------------- ----------------------------------------
    *BAFAB4wCwQL+               Typ=208 Len=10: 2,4,1,64,7,140,2,193,2,254
    逻辑ROWID的DUMPl果前两位都??Q最后一位都?54Q(我还没有发现其他的情况)Q由于逻辑ROWID和主键的值有养I所以长度是不定的,因此应该是用来表C开始和l束的?
    W??位和物理ROWID一P表示的是相对表空间的数据文g号乘?4的倹{?
    W??位表C条记录在数据文g的第几个BLOCK中?
    从第7位开始到DUMPl果的倒数W二位,表示主键的倹{首先是主键中第一个字D늚长度Q这里是2Q然后是主键的|׃是NUMBERcdQ因?93Q?表示数?。如果是多个字段l成的主键,W一个字D之后是W二个字D늚长度Q然后是W二个字D늚值……?
    SQL> select (1*256 + 64)/64 from dual;
    (1*256+64)/64
    -------------
                5
    SQL> select 7*256 + 140 from dual;
     7*256+140
    ----------
          1932
    SQL> alter system dump datafile 5 block 1932;
    pȝ已更攏V?
    扑ֈ相应的dump文gQ可以发现刚才插入的记录?
    Dump file f:oracleadmintest4udumptest4_ora_3828.trc
    Thu Dec 23 00:17:53 2004
    ORACLE V9.2.0.4.0 - Production vsnsta=0
    vsnsql=12 vsnxtr=3
    Windows 2000 Version 5.1 Service Pack 1, CPU type 586
    Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
    With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
    JServer Release 9.2.0.4.0 - Production
    Windows 2000 Version 5.1 Service Pack 1, CPU type 586
    Instance name: test4
    Redo thread mounted by this instance: 1
    Oracle process number: 9
    Windows thread id: 3828, image: ORACLE.EXE
    *** 2004-12-23 00:17:53.361
    *** SESSION ID:(8.82) 2004-12-23 00:17:53.301
    Start dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932
    buffer tsn: 5 rdba: 0x0140078c (5/1932)
    scn: 0x0000.00e9f122 seq: 0x01 flg: 0x02 tail: 0xf1220601
    frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
    Block header dump:  0x0140078c
     Object id on Block? Y
     seg/obj: 0x1e48  csc: 0x00.e9f113  itc: 2  flg: E  typ: 2 - INDEX
         brn: 0  bdba: 0x1400789 ver: 0x01
         inc: 0  exflg: 0
     
     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
    0x02   0x0005.008.000000e7  0x00800226.005c.24  --U-    1  fsc 0x0000.00e9f122
     
    Leaf block dump
    ===============
    header address 71963236=0x44a1264
    kdxcolev 0
    KDXCOLEV Flags = - - -
    kdxcolok 0
    kdxcoopc 0x90: opcode=0: iot flags=I-- is converted=Y
    kdxconco 1
    kdxcosdc 0
    kdxconro 1
    kdxcofbo 38=0x26
    kdxcofeo 8026=0x1f5a
    kdxcoavs 7988
    kdxlespl 0
    kdxlende 0
    kdxlenxt 0=0x0
    kdxleprv 0=0x0
    kdxledsz 0
    kdxlebksz 8036
    row#0[8026] flag: K----, lock: 2
    col 0; len 2; (2):  c1 02
    tl: 5 fb: --H-FL-- lb: 0x0  cc: 1
    col  0: [ 1]
    Dump of memory from 0x044A31C7 to 0x044A31C8
    44A31C0          61010100                        [...a]       
    ----- end of leaf block dump -----
    End dump data blocks tsn: 5 file#: 5 minblk 1932 maxblk 1932
    可以看到Q根据DUMPl果????位可以定位记录的物理位置?
    需要注意的是,索引l织表以主键的顺序存储数据,因此插入、更新和删除数据都可能造成一条记录的物理位置发生变化Q这旉过ROWID中的DATAFILE和BLOCK的信息可能就无法正确定位到记录的物理位置。当Ҏ(gu)逻辑ROWID讉K索引l织表时Q首先会Ҏ(gu)DATAFILE和BLOCK信息L到相应的BLOCKQ检查数据是否在q个BLOCK中,如果不在Q就通过逻辑ROWID中的主键信息去通过索引扫描Q找到这条记录。这是Oracle文档在提到的physical guess?
    下面看一个由字符串和日期l成联合主键的例子?
    SQL> create table test_index2 (id char(4), time date,
      2  constraint pk_test_index2 primary key (id, time)) organization index;
    表已创徏?
    SQL> insert into test_index2 values ('1', sysdate);
    已创?1 行?
    SQL> col dump_rowid format a75
    SQL> select rowid, dump(rowid) dump_rowid from test_index2;
    ROWID                        DUMP_ROWID
    ---------------------------- ------------------------------------------------------------------
    *BAFAB5QEMSAgIAd4aAwXASMT/g  Typ=208 Len=20: 2,4,1,64,7,148,4,49,32,32,32,7,120,104,12,23,1,35,19,254
    可以看出Q第7位是字段id的长?Q然后是字符?和三个空格的ASCII码,q是字符串的存储格式Q后面跟着?是字Dtime长度Q后面七位是日期的存储格式。在逻辑ROWID中,数倹{字W和日期cd的存储格式都和它们本w的存储格式一_q里不在赘述?
    一般情况下Q用一位来表示长度Q但是如果长度超q了127Q?6q制DUMP的结果是7FQ,则长度开始用两位表示。第一位以8开_q个8只是标识位,表明长度字段现在׃位来表示。例如长?28表示?080Q而支持的最大?800表示?ED8?br />==============================================================
    Oracle基本数据cd存储格式析Q五Q——RAWcd
    发表?yangtingkun | 发表旉: 2004q十二月23? 15:20
    和其他数据类型相比,RAWcd的存储显得直观多了,它和SELECT时数据展C的值完全一栗(SELECT时是按照16q制展示的)
     
    SQL> create table test_raw (id number, raw_date raw(10));
    表已创徏?br />SQL> insert into test_raw values (1, hextoraw('ff'));
    已创?1 行?br />SQL> drop table test_raw;
    表已丢弃?br />SQL> create table test_raw (raw_col raw(10));
    表已创徏?br />SQL> insert into test_raw values (hextoraw('ff'));
    已创?1 行?br />SQL> insert into test_raw values (hextoraw('0'));
    已创?1 行?br />SQL> insert into test_raw values (hextoraw('23fc'));
    已创?1 行?br />SQL> insert into test_raw values (hextoraw('fffffffffff'));
    已创?1 行?br />SQL> insert into test_raw values (hextoraw('ffffffffffffffffffff'));
    已创?1 行?br />SQL> insert into test_raw values (utl_raw.cast_to_raw('051'));
    已创?1 行?br />SQL> select raw_col, dump(raw_col, 16) dump_raw from test_raw;
    RAW_COL              DUMP_RAW
    -------------------- -----------------------------------------------
    FF                   Typ=23 Len=1: ff
    00                   Typ=23 Len=1: 0
    23FC                 Typ=23 Len=2: 23,fc
    0FFFFFFFFFFF         Typ=23 Len=6: f,ff,ff,ff,ff,ff
    FFFFFFFFFFFFFFFFFFFF Typ=23 Len=10: ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
    303531               Typ=23 Len=3: 30,35,31
    已选择6行?br />RAWcd的存储很单,Ҏ(gu)字段的查询结果和DUMP的结果就一目了然了?br />需要注意的是,两种转化为RAW的函C间的差别。当使用HEXTORAWӞ会把字符串中数据当作16q制数。而用UTL_RAW.CAST_TO_RAWӞ直接把字W串中每个字W的ASCII码存攑ֈRAWcd的字D中?br />SQL> insert into test_raw values ('gg');
    insert into test_raw values ('gg')
                                 *
    ERROR 位于W?1 ?
    ORA-01465: 无效的十六进制数?br />SQL> insert into test_raw values (hextoraw('gg'));
    insert into test_raw values (hextoraw('gg'))
                                          *
    ERROR 位于W?1 ?
    ORA-01465: 无效的十六进制数?br />SQL> insert into test_raw values (utl_raw.cast_to_raw('gg'));
    已创?1 行?br />SQL> select raw_col, dump(raw_col, 16) dump_raw from test_raw;
    RAW_COL              DUMP_RAW
    -------------------- ----------------------------------------------
    FF                   Typ=23 Len=1: ff
    00                   Typ=23 Len=1: 0
    23FC                 Typ=23 Len=2: 23,fc
    6767                 Typ=23 Len=2: 67,67
    0FFFFFFFFFFF         Typ=23 Len=6: f,ff,ff,ff,ff,ff
    FFFFFFFFFFFFFFFFFFFF Typ=23 Len=10: ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
    303531               Typ=23 Len=3: 30,35,31
    已选择7行?br />

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=607570



    風向逆轉 - p爪哇 2006-03-20 23:37 发表评论
    ]]>
    [收藏]Windows环境下的Oracle服务http://www.tkk7.com/iKingQu/articles/36490.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:35:00 GMThttp://www.tkk7.com/iKingQu/articles/36490.htmlhttp://www.tkk7.com/iKingQu/comments/36490.htmlhttp://www.tkk7.com/iKingQu/articles/36490.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36490.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36490.html注:SID - 数据库标?br />    HOME_NAME - Oracle Home名称Q如OraHome92、OraHome81
    Q?QOracleServiceSID                       
    数据库服务,q个服务会自动地启动和停止数据库。如果安装了一个数据库Q它的缺省启动类型ؓ自动。服务进EؓORACLE.EXEQ参数文件initSID.oraQ日志文件SIDALRT.logQ控制台SVRMGRL.EXE、SQLPLUS.EXE?br />
    Q?QOracleHOME_NAMETNSListener
    监听器服务,服务只有在数据库需要远E访问时才需要(无论是通过另外一C是在本地通过 SQL*Net |络协议都属于远E访问)Q不用这个服务就可以讉K本地数据库,它的~省启动cd动。服务进EؓTNSLSNR.EXEQ参数文件Listener.oraQ日志文件listener.logQ控制台LSNRCTL.EXEQ默认端?521?526?br />
    Q?QOracleHOME_NAMEAgent
    OEM代理服务Q接收和响应来自OEM控制台的d和事件请求,只有使用OEM理数据库时才需要,它的~省启动cd动。服务进EؓDBSNMP.EXEQ参数文件snmp_rw.oraQ日志文件nmi.logQ控制台LSNRCTL.EXEQ默认端?748?br />
    Q?QOracleHOME_NAMEClientCache       
    名字~存服务Q服务缓存用于连接远E数据库的Oracle Names 数据。它的缺省启动类型是手动。然而,除非有一台Oracle Names 服务器,否则没有必要q行q个服务。服务进EؓONRSD.EXEQ参数文件NAMES.ORAQ日志文件ONRSD.LOGQ控制台NAMESCTL.EXE?br />
    Q?QOracleHOME_NAMECMAdmin                       
    q接理服务Q是构徏Connection Manager服务器所用,只有服务器作为Connection Manager才需要,它的~省启动cd是手动。服务进EؓCMADMIN.EXEQ参数文件CMAN.ORAQ日志文件CMADM_PID.TRCQ控制台CMCTL.EXEQ默认端?830?br />
    Q?QOracleHOME_NAMECMan                       
    q接|关服务Q是构徏Connection Manager服务器所用,只有服务器作为Connection Manager才需要,它的~省启动cd是手动。服务进EؓCMGW.EXEQ参数文件CMAN.ORAQ日志文件CMAN_PID.TRCQ控制台CMCTL.EXEQ默认端?630?br />
    Q?QOracleHOME_NAMEDataGatherer
    性能包数据采集服务,除非使用Oracle Capacity Planner ?Oracle Performance ManagerQ否则不需要启动,它的~省启动cd是手动。服务进EؓVPPDC.EXEQ日志文件alert_dg.logQ控制台vppcntl.exe?br />
    Q?QOracleHOME_NAMEHTTPServer
    Oracle提供的WEB服务器,一般情况下我们只用它来讉KOracle Apache 目录下的Web 面Q比如说JSP 或者modplsql 面。除非你使用它作Z的HTTP服务Q否则不需要启动(若启动它会接IIS的服务)Q它的缺省启动类型是手动。服务进EؓAPACHE.EXEQ参数文件httpd.confQ默认端?0?br />
    Q?QOracleHOME_NAMEPagingServer
    通过一个用调制解调器的数字传呼机或者电(sh)子邮件发告(没试q)Q它的缺省启动类型是手动。服务进EPAGNTSRV.EXEQ日志文件paging.log?br />
    Q?0QOracleHOME_NAMENames
    Oracle Names服务Q只有服务器作ؓNames Server才需要,它的~省启动cd是手动。服务进ENAMES.EXEQ参数文件NAMES.ORAQ日志文件NAMES.LOGQ控制台NAMESCTL.EXEQ默认端?575?br />
    Q?1QOracleSNMPPeerMasterAgent
    SNMP服务代理Q用于支持SNMP的网Y件对服务器的理Q除非你使用|管工具监控数据库的情况Q否则不需要启动,它的~省启动cd是手动。服务进EؓAGNTSVC.EXEQ参数文件MASTER.CFGQ默认端?61?br />
    Q?2QOracleSNMPPeerEncapsulater
    SNMP协议装服务Q用于SNMP协议转换Q除非你使用一个不兼容的SNMP代理服务Q否则不需要启动,它的~省启动cd是手动。服务进EؓENCSVC.EXEQ参数文件ENCAPS.CFGQ默认端?161?br />
    Q?3QOracleHOME_NAMEManagementServer
    OEM理服务Q用OEM旉要,它的~省启动cd是手动。服务进EؓOMSNTSVR.EXEQ日志文件oms.nohup?br />
    作者BlogQ?/strong> http://blog.csdn.net/lm20224/


    ]]>
    [收藏]数据库连接池Java实现结http://www.tkk7.com/iKingQu/articles/36482.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:24:00 GMThttp://www.tkk7.com/iKingQu/articles/36482.htmlhttp://www.tkk7.com/iKingQu/comments/36482.htmlhttp://www.tkk7.com/iKingQu/articles/36482.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36482.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36482.html目的Q?/h3>
    • 消除数据库频J连接带来的开销和瓶颈?/li>

    解决Ҏ(gu)Q?/h3>
    • 不过多的限制用户的用,既不能太多的要求用户按规定的Ҏ(gu)得到和用数据库q?/li>
    • 量保持用户的习?/li>

    目前的很多方法都是要求用户只能按规定Ҏ(gu)使用q接Q不能用直接关闭数据连接的Ҏ(gu)。解军_法就是用代理类Q来中间解决。可以参?a >http://www-900.ibm.com/developerWorks/cn/java/l-connpoolproxy/index.shtml

    • 能维护连接的正常状?/li>

    因ؓ针对数据库连接创建的资源Q如果不能及时的释放Q就会媄响下一ơ数据连接的使用。例如在sql 2k中,一个连接不同创建多条Statement否则操作时会有数据连接占U的异常Q所以必d归还q接以后释放q些资源?/p>

    
       //?/font>断是使用了createStatement语句
       if (CREATESTATE.equals(method.getName()))
       {
        obj = method.invoke(conn, args);
        statRef = (Statement)obj;//记录语句
        return obj;
       }

       //?/font>断是否调用了close的方法,如果调用closeҎ(gu)则把q接|ؓ无用状?br />   if(CLOSE.equals(method.getName()))
       {
        //?/font>|不使用标志
        setIsFree(false);
        //查是否有后箋工作Q清除该q接无用资源
        if (statRef != null)
         statRef.close();
        if (prestatRef != null)
         prestatRef.close();
        return null;
       }
    • 正确保护cM被违例?/li>

    一个考虑是不能让用户随便用代理类Q而只能自׃用,一个就是用内部U有c,一个就是用只有指定类才能调用的标志。我的实现就是采用后者?/p>
     /**
      * 创徏q接的工厂,只能让工厂调?br />  * @param factory 要调用工厂,q且一定被正确初始?br />  * @param param q接参数
      * @return q接
      */
     static public _Connection getConnection(ConnectionFactory factory, ConnectionParam param)
     {
      if (factory.isCreate())//判断是否正确初始化的工厂
      {
       _Connection _conn = new _Connection(param);
       return _conn;
      }
      else
       return null;
     }

    • 提供良好的用h口,单实?/li>

    使用静态方法创建工厂,然后来得到连接,使用完全和普通的ConnectionҎ(gu)一P没有限制。同时ؓ了方便,讄了连接参数类和工厂参数类?/p>

    •  ConnectionParam param = new ConnectionParam(driver,url,user,password);
        ConnectionFactory cf = null;//new ConnectionFactory(param, new FactoryParam());
        try{
         cf = new ConnectionFactory(param,new FactoryParam());
         Connection conn1 = cf.getFreeConnection();
         Connection conn2 = cf.getFreeConnection();
         Connection conn3 = cf.getFreeConnection();
         Statement stmt = conn1.createStatement();
         ResultSet rs = stmt.executeQuery("select * from requests");
         if (rs.next())
         {
          System.out.println("conn1 y");  
         }
         else
         {
          System.out.println("conn1 n");  
         } 
         stmt.close();
         conn1.close();  
    • Z实现q接池的正常q作Q用了单态模

     /**
      * 使用指定的参数创Z个连接池
      */
     public ConnectionFactory(ConnectionParam param, FactoryParam fparam)
      throws SQLException
     {
      //?/font>允许参数为空
      if ((param == null)||(fparam == null))
       throw new SQLException("ConnectionParam和FactoryParam不能为空");
      if (m_instance == null)
      {
       synchronized(ConnectionFactory.class){
        if (m_instance == null)
        {
         //new instance
         //?/font>数定?br />     m_instance = new ConnectionFactory();
         m_instance.connparam = param;
         m_instance.MaxConnectionCount = fparam.getMaxConn();
         m_instance.MinConnectionCount = fparam.getMinConn();
         m_instance.ManageType = fparam.getType();
         m_instance.isflag = true;
         //?/font>始化Q创建MinConnectionCount个连?br />     System.out.println("connection factory 创徏Q?);
         try{
          for (int i=0; i < m_instance.MinConnectionCount; i++)
          {
           _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
           if (_conn == null) continue;
           System.out.println("connection创徏");
           m_instance.FreeConnectionPool.add(_conn);//加入I闲q接?br />       m_instance.current_conn_count ++;
           //?/font>志是否支持事?br />       m_instance.supportTransaction = _conn.isSupportTransaction();    
          }
         }
         catch(Exception e)
         {
          e.printStackTrace();
         }
         //?/font>据策略判断是否需要查?br />     if (m_instance.ManageType != 0)
         {
          Thread t = new Thread(new FactoryMangeThread(m_instance));
          t.start();
         } 
        }
       }
      }
     }
     
    • q接池的理

    对于q接池的理Q我是设想用静态管理和动态管理两U策略,讄了最大限Ӟ和恒定的q接数。用了2个池Q一个空闲池Q一个用池。静态就是用的时候发现空闲连接不够再L查。动态就是用了一个线E定时检查?/p>

     //Ҏ(gu){略判断是否需要查?br />     if (m_instance.ManageType != 0)
         {
          Thread t = new Thread(new FactoryMangeThread(m_instance));
          t.start();
         }
     //q接池调度线E?br />public class FactoryMangeThread implements Runnable {
     ConnectionFactory cf = null;
     long delay = 1000;
     public FactoryMangeThread(ConnectionFactory obj)
     {
      cf = obj;
     }
     /* (non-Javadoc)
      * @see java.lang.Runnable#run()
      */
     public void run() {
      while(true){
       try{
        Thread.sleep(delay);
       }
       catch(InterruptedException e){}
       System.out.println("eeeee");
       //?/font>断是否已l关闭了工厂Q那退出监?br />   if (cf.isCreate())
        cf.schedule();
       else
        System.exit(1);
      }
     }
    }

    最后给出完整的源代码:


    _Connectio.java

    package scut.ailab.connectionpool;
    import java.lang.reflect.*;
    import java.sql.*;
    /**
     * @author youyongming
     * 定义数据库连接的代理c?br /> */
    public class _Connection implements InvocationHandler {
     //?/font>义连?br /> private Connection conn = null;
     //?/font>义监控连接创建的语句
     private Statement statRef = null;
     private PreparedStatement prestatRef = null;
     //?/font>否支持事务标?br /> private boolean supportTransaction = false;
     //?/font>据库的忙状?br /> private boolean isFree = false;
     //最后一ơ访问时?br /> long lastAccessTime = 0;
     //?/font>义要接管的函数的名字
     String CREATESTATE = "createStatement";
     String CLOSE = "close";
     String PREPARESTATEMENT = "prepareStatement";
     String COMMIT = "commit";
     String ROLLBACK = "rollback";
     /**
      * 构造函敎ͼ采用U有Q防止被直接创徏
      * @param param q接参数
      */
     private _Connection(ConnectionParam param) {
      //?/font>录日?br />  
      try{
       //?/font>?br />   Class.forName(param.getDriver()).newInstance();
       conn = DriverManager.getConnection(param.getUrl(),param.getUser(), param.getPassword());   
       DatabaseMetaData dm = null;
       dm = conn.getMetaData();
       //?/font>断是否支持事?br />   supportTransaction = dm.supportsTransactions();
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
     }

     /* (non-Javadoc)
      * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
      */
     public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
       Object obj = null;
       //?/font>断是否调用了close的方法,如果调用closeҎ(gu)则把q接|ؓ无用状?br />   if(CLOSE.equals(method.getName()))
       {
        //?/font>|不使用标志
        setIsFree(false);
        //查是否有后箋工作Q清除该q接无用资源
        if (statRef != null)
         statRef.close();
        if (prestatRef != null)
         prestatRef.close();
        return null;
       }
       //?/font>断是使用了createStatement语句
       if (CREATESTATE.equals(method.getName()))
       {
        obj = method.invoke(conn, args);
        statRef = (Statement)obj;//记录语句
        return obj;
       }
       //?/font>断是使用了prepareStatement语句
       if (PREPARESTATEMENT.equals(method.getName()))
       {
        obj = method.invoke(conn, args);
        prestatRef = (PreparedStatement)obj;
        return obj;
       }
       //?/font>果不支持事务Q就不执行该事物的代?br />   if ((COMMIT.equals(method.getName())||ROLLBACK.equals(method.getName())) && (!isSupportTransaction()))
        return null;   
       obj = method.invoke(conn, args); 
       //?/font>|最后一ơ访问时_以便及时清除时的连?br />   lastAccessTime = System.currentTimeMillis();
       return obj;
     }
     /**
      * 创徏q接的工厂,只能让工厂调?br />  * @param factory 要调用工厂,q且一定被正确初始?br />  * @param param q接参数
      * @return q接
      */
     static public _Connection getConnection(ConnectionFactory factory, ConnectionParam param)
     {
      if (factory.isCreate())//判断是否正确初始化的工厂
      {
       _Connection _conn = new _Connection(param);
       return _conn;
      }
      else
       return null;
     }
     
     public Connection getFreeConnection() {
      //q?/font>回数据库q接conn的接类Q以便截住closeҎ(gu)
      Connection conn2 = (Connection)Proxy.newProxyInstance(
       conn.getClass().getClassLoader(),
       conn.getClass().getInterfaces(),this);
      return conn2;
     }
     /**
      * 该方法真正的关闭了数据库的连?br />  * @throws SQLException
      */
     void close() throws SQLException{
      //?/font>于类属性conn是没有被接管的连接,因此一旦调用closeҎ(gu)后就直接关闭q接
      conn.close();
     }
       
     public void setIsFree(boolean value)
     {
      isFree = value;
     }
     
     public boolean isFree() {
      return isFree;
     } 
     /**
      * 判断是否支持事务
      * @return boolean
      */
     public boolean isSupportTransaction() {
      return supportTransaction;
     } 
    }


    ConnectionFactory.java

     package scut.ailab.connectionpool;
    /**
     * @author youyongming
     *
     */
    import java.util.LinkedHashSet;
    import java.sql.*;
    import java.util.Iterator;
    public class ConnectionFactory {
     private static ConnectionFactory m_instance = null;
     //?/font>使用的连接池
     private LinkedHashSet ConnectionPool = null;
     //I?/font>闲连接池
     private LinkedHashSet FreeConnectionPool = null;
     //最大连接数
     private int MaxConnectionCount = 4;
     //最连接数
     private int MinConnectionCount = 2;
     //?/font>前连接数
     private int current_conn_count = 0;
     //q?/font>接参?br /> private ConnectionParam connparam = null;
     //?/font>否创建工厂的标志
     private boolean isflag = false;
     //?/font>否支持事?br /> private boolean supportTransaction = false;
     //?/font>义管理策?br /> private int ManageType = 0;
     private ConnectionFactory() {
      ConnectionPool = new LinkedHashSet();
      FreeConnectionPool = new LinkedHashSet();
     }
     
     /**
      * 使用指定的参数创Z个连接池
      */
     public ConnectionFactory(ConnectionParam param, FactoryParam fparam)
      throws SQLException
     {
      //?/font>允许参数为空
      if ((param == null)||(fparam == null))
       throw new SQLException("ConnectionParam和FactoryParam不能为空");
      if (m_instance == null)
      {
       synchronized(ConnectionFactory.class){
        if (m_instance == null)
        {
         //new instance
         //?/font>数定?br />     m_instance = new ConnectionFactory();
         m_instance.connparam = param;
         m_instance.MaxConnectionCount = fparam.getMaxConn();
         m_instance.MinConnectionCount = fparam.getMinConn();
         m_instance.ManageType = fparam.getType();
         m_instance.isflag = true;
         //?/font>始化Q创建MinConnectionCount个连?br />     System.out.println("connection factory 创徏Q?);
         try{
          for (int i=0; i < m_instance.MinConnectionCount; i++)
          {
           _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
           if (_conn == null) continue;
           System.out.println("connection创徏");
           m_instance.FreeConnectionPool.add(_conn);//加入I闲q接?br />       m_instance.current_conn_count ++;
           //?/font>志是否支持事?br />       m_instance.supportTransaction = _conn.isSupportTransaction();    
          }
         }
         catch(Exception e)
         {
          e.printStackTrace();
         }
         //?/font>据策略判断是否需要查?br />     if (m_instance.ManageType != 0)
         {
          Thread t = new Thread(new FactoryMangeThread(m_instance));
          t.start();
         } 
        }
       }
      }
     }
     
     /**
      * 标志工厂是否已经创徏
      * @return boolean
      */ 
     public boolean isCreate()
     {
      return m_instance.isflag;
     }
     
     /**
      * 从连接池中取一个空闲的q接
      * @return Connection
      * @throws SQLException
      */
     public synchronized Connection getFreeConnection()
      throws SQLException
     {
      Connection conn = null;
      //?/font>取空闲连?br />  Iterator iter = m_instance.FreeConnectionPool.iterator();
      while(iter.hasNext()){
       _Connection _conn = (_Connection)iter.next();
       //?/font>到未用连?br />   if(!_conn.isFree()){
        conn = _conn.getFreeConnection();
        _conn.setIsFree(true);
        //U?/font>出空闲区
        m_instance.FreeConnectionPool.remove(_conn);
        //?/font>入连接池 
        m_instance.ConnectionPool.add(_conn);   
        break;
       }
      }
      //查空闲池是否为空
      if (m_instance.FreeConnectionPool.isEmpty())
      {
       //?/font>查是否能够分?br />   if (m_instance.current_conn_count < m_instance.MaxConnectionCount)
       {
       //?/font>接到I闲q接?br />    int newcount = 0 ;
        //?/font>得要建立的数?br />    if (m_instance.MaxConnectionCount - m_instance.current_conn_count >=m_instance.MinConnectionCount)
        {
         newcount = m_instance.MinConnectionCount;
        }
        else
        {
         newcount = m_instance.MaxConnectionCount - m_instance.current_conn_count;
        }
        //?/font>?br />    for (int i=0;i <newcount; i++)
        {
         _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
         m_instance.FreeConnectionPool.add(_conn);
         m_instance.current_conn_count ++;
        }
       }
       else
       {//如果不能新徏Q检查是否有已经归还的连?br />    iter = m_instance.ConnectionPool.iterator();
        while(iter.hasNext()){
         _Connection _conn = (_Connection)iter.next();
         if(!_conn.isFree()){
          conn = _conn.getFreeConnection();
          _conn.setIsFree(false);
          m_instance.ConnectionPool.remove(_conn); 
          m_instance.FreeConnectionPool.add(_conn);   
          break;
         }
        }    
       }
      }//if (FreeConnectionPool.isEmpty())
     //?/font>ơ检查是否能分配q接
      if(conn == null){
       iter = m_instance.FreeConnectionPool.iterator();
       while(iter.hasNext()){
        _Connection _conn = (_Connection)iter.next();
        if(!_conn.isFree()){
         conn = _conn.getFreeConnection();
         _conn.setIsFree(true);
         m_instance.FreeConnectionPool.remove(_conn); 
         m_instance.ConnectionPool.add(_conn);   
         break;
        }
       }
       if(conn == null)//如果不能则说明无q接可用
        throw new SQLException("没有可用的数据库q接");
      }
      System.out.println("get connection");
      return conn;
     }
     
     /**
      * 关闭该连接池中的所有数据库q接
      * @throws SQLException
      */
     public synchronized void close() throws SQLException
     {
      this.isflag = false;
      SQLException excp = null;
      //?/font>闭空闲池
      Iterator iter = m_instance.FreeConnectionPool.iterator();
      while(iter.hasNext()){
       try{
        ((_Connection)iter.next()).close();
        System.out.println("close connection:free");
        m_instance.current_conn_count --;
       }catch(Exception e){
        if(e instanceof SQLException)
         excp = (SQLException)e;
       }
      }
      //?/font>闭在使用的连接池
      iter = m_instance.ConnectionPool.iterator();
      while(iter.hasNext()){
       try{
        ((_Connection)iter.next()).close();
        System.out.println("close connection:inused");
        m_instance.current_conn_count --;
       }catch(Exception e){
        if(e instanceof SQLException)
         excp = (SQLException)e;
       }
      }  
      if(excp != null)
       throw excp;
     } 
     
     /**
      * q回是否支持事务
      * @return boolean
      */
     public boolean isSupportTransaction() {
      return m_instance.supportTransaction;
     }  
     /**
      * q接池调度管?br />  *
      */
     public void schedule()
     {
      Connection conn = null;
      //?/font>查是否能够分?br />  Iterator iter = null;
      //查是否有已经归还的连?br />  {
       iter = m_instance.ConnectionPool.iterator();
       while(iter.hasNext()){
        _Connection _conn = (_Connection)iter.next();
        if(!_conn.isFree()){
         conn = _conn.getFreeConnection();
         _conn.setIsFree(false);
         m_instance.ConnectionPool.remove(_conn); 
         m_instance.FreeConnectionPool.add(_conn);   
         break;
        }
       }    
      }
      if (m_instance.current_conn_count < m_instance.MaxConnectionCount)
      {
       //?/font>接到I闲q接?br />   int newcount = 0 ;
       //?/font>得要建立的数?br />   if (m_instance.MaxConnectionCount - m_instance.current_conn_count >=m_instance.MinConnectionCount)
       {
        newcount = m_instance.MinConnectionCount;
       }
       else
       {
        newcount = m_instance.MaxConnectionCount - m_instance.current_conn_count;
       }
       //?/font>?br />   for (int i=0;i <newcount; i++)
       {
        _Connection _conn = _Connection.getConnection(m_instance, m_instance.connparam);
        m_instance.FreeConnectionPool.add(_conn);
        m_instance.current_conn_count ++;
       }
      }
     }
    }


    ConnectionParam.java

     package scut.ailab.connectionpool;
    import java.io.Serializable;
    /**
     * @author youyongming
     * 实现数据库连接的参数c?br /> */
    public class ConnectionParam implements Serializable {
     private String driver;    //?/font>据库驱动E序
     private String url;   //?/font>据连接的URL
     private String user;    //?/font>据库用户?br /> private String password;   //?/font>据库密码
     
     /**
      * 唯一的构造函敎ͼ需要指定连接的四个必要参数
      * @param driver 数据驱动
      * @param url  数据库连接url
      * @param user  用户?br />  * @param password 密码
      */
     public ConnectionParam(String driver,String url,String user,String password)
     {
      this.driver = driver;
      this.url = url;
      this.user = user;
      this.password = password;
     }
     public String getDriver() {
      return driver;
     }
     public String getPassword() {
      return password;
     }
     public String getUrl() {
      return url;
     }
     public String getUser() {
      return user;
     }
     public void setDriver(String driver) {
      this.driver = driver;
     }
     public void setPassword(String password) {
      this.password = password;
     }
     public void setUrl(String url) {
      this.url = url;
     }
     public void setUser(String user) {
      this.user = user;
     }
     /**
      * @see java.lang.Object#clone()
      */
     public Object clone(){
      ConnectionParam param = new ConnectionParam(driver,url,user,password);
      return param;
     }
     /**
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public boolean equals(Object obj) {
      if(obj instanceof ConnectionParam){
       ConnectionParam param = (ConnectionParam)obj;
       return ((driver.compareToIgnoreCase(param.getDriver()) == 0)&&
       (url.compareToIgnoreCase(param.getUrl()) == 0)&&
       (user.compareToIgnoreCase(param.getUser()) == 0)&&
       (password.compareToIgnoreCase(param.getPassword()) == 0));
      }
      return false;
     }
    }


    FactoryMangeThread.java

     /*
     * Created on 2003-5-13
     *
     * To change the template for this generated file go to
     * Window>Preferences>Java>Code Generation>Code and Comments
     */
    package scut.ailab.connectionpool;
    /**
     * @author youyongming
     *
     */
    //q?/font>接池调度U程
    public class FactoryMangeThread implements Runnable {
     ConnectionFactory cf = null;
     long delay = 1000;
     public FactoryMangeThread(ConnectionFactory obj)
     {
      cf = obj;
     }
     /* (non-Javadoc)
      * @see java.lang.Runnable#run()
      */
     public void run() {
      while(true){
       try{
        Thread.sleep(delay);
       }
       catch(InterruptedException e){}
       System.out.println("eeeee");
       //?/font>断是否已l关闭了工厂Q那退出监?br />   if (cf.isCreate())
        cf.schedule();
       else
        System.exit(1);
      }
     }
    }


    FactoryParam.java

     /*
     * Created on 2003-5-13
     *
     * To change the template for this generated file go to
     * Window>Preferences>Java>Code Generation>Code and Comments
     */
    package scut.ailab.connectionpool;
    /**
     * @author youyongming
     *
     */
    //q?/font>接池工厂参数
    public class FactoryParam {
     //最大连接数
     private int MaxConnectionCount = 4;
     //最连接数
     private int MinConnectionCount = 2;
     //?/font>收策?br /> private int ManageType = 0;
     
     public FactoryParam() {
     }
     
     /**
      * 构造连接池工厂参数的对?br />  * @param max 最大连接数
      * @param min 最连接数
      * @param type 理{略
      */
     public FactoryParam(int max, int min, int type)
     {
      this.ManageType = type;
      this.MaxConnectionCount = max;
      this.MinConnectionCount = min;
     }
     
     /**
      * 讄最大的q接?br />  * @param value
      */
     public void setMaxConn(int value)
     {
      this.MaxConnectionCount = value;
     }
     /**
      * 获取最大连接数
      * @return
      */
     public int getMaxConn()
     {
      return this.MaxConnectionCount;
     }
     /**
      * 讄最连接数
      * @param value
      */
     public void setMinConn(int value)
     {
      this.MinConnectionCount = value;
     }
     /**
      * 获取最连接数
      * @return
      */
     public int getMinConn()
     {
      return this.MinConnectionCount;
     }
     public int getType()
     {
      return this.ManageType;
     }
    }


    testmypool.java

     /*
     * Created on 2003-5-13
     *
     * To change the template for this generated file go to
     * Window>Preferences>Java>Code Generation>Code and Comments
     */
    package scut.ailab.connectionpool;
    /**
     * @author youyongming
     *
     */
    import java.sql.*;
    public class testmypool {
     public void test1()
     {
      String user = "DevTeam";
      String password = "DevTeam";
      String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
      String url = "jdbc:odbc:gfqh2";
      ConnectionParam param = new ConnectionParam(driver,url,user,password);
      ConnectionFactory cf = null;//new ConnectionFactory(param, new FactoryParam());
      try{
       cf = new ConnectionFactory(param,new FactoryParam());
       Connection conn1 = cf.getFreeConnection();
       Connection conn2 = cf.getFreeConnection();
       Connection conn3 = cf.getFreeConnection();
       Statement stmt = conn1.createStatement();
       ResultSet rs = stmt.executeQuery("select * from requests");
       if (rs.next())
       {
        System.out.println("conn1 y");  
       }
       else
       {
        System.out.println("conn1 n");  
       } 
       stmt.close();
       conn1.close();  
       Connection conn4 = cf.getFreeConnection();
       Connection conn5 = cf.getFreeConnection();
       stmt = conn5.createStatement();
       rs = stmt.executeQuery("select * from requests");
       if (rs.next())
       {
        System.out.println("conn5 y");  
       }
       else
       {
        System.out.println("conn5 n");  
       } 
       conn2.close();
       conn3.close();
       conn4.close();
       conn5.close();
       }
      catch(Exception e)
      {
       e.printStackTrace();
      }
      finally{
       try{
        cf.close();
       }
       catch(Exception e)
       {
        e.printStackTrace();
       }
      } 
     }
     public static void main(String[] args) {
      String user = "DevTeam";
      String password = "DevTeam";
      String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
      String url = "jdbc:odbc:gfqh2";
      ConnectionParam param = new ConnectionParam(driver,url,user,password);
      ConnectionFactory cf = null;//new ConnectionFactory(param,new FactoryParam());
      try{
       cf = new ConnectionFactory(param,new FactoryParam());
       ConnectionFactory cf1= new ConnectionFactory(param,new FactoryParam());
       Connection conn1 = null;
       long time = System.currentTimeMillis();
       for (int i=0; i <10;i++)
       {
        conn1 = cf.getFreeConnection();
        Statement stmt = conn1.createStatement();
        ResultSet rs = stmt.executeQuery("select * from requests");
        if (rs.next())
        {
         System.out.println("conn1 y");  
        }
        else
        {
         System.out.println("conn1 n");  
        } 
        conn1.close();  
       }
       System.out.println("pool:" + (System.currentTimeMillis()-time));
       time = System.currentTimeMillis();
       Class.forName(param.getDriver()).newInstance();
       for (int i=0; i <10;i++)
       {
        conn1 = DriverManager.getConnection(param.getUrl(),param.getUser(), param.getPassword());   
        Statement stmt = conn1.createStatement();
        ResultSet rs = stmt.executeQuery("select * from requests");
        if (rs.next())
        {
         System.out.println("conn1 y");  
        }
        else
        {
         System.out.println("conn1 n");  
        } 
        conn1.close();  
       }   
       System.out.println("no pool:" + (System.currentTimeMillis()-time));
      }
      catch(Exception e)
      {
       e.printStackTrace();
      }
      finally{
       try{
        cf.close();
       }
       catch(Exception e)
       {
        e.printStackTrace();
       }
      }
     }
    }


    原文链接:http://www.jaron.cn/chs_db/16/2003-09/20030916110224-101181.html

    ]]>[收藏]Tomcat5配置Mysql JDBC数据库连接池 http://www.tkk7.com/iKingQu/articles/36473.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 15:14:00 GMThttp://www.tkk7.com/iKingQu/articles/36473.htmlhttp://www.tkk7.com/iKingQu/comments/36473.htmlhttp://www.tkk7.com/iKingQu/articles/36473.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36473.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36473.html如果只是对MySql感兴可以照抄这短文,如果想配|其他数据库cd的连接池Q也可以做简单修改参数即可用。?br />

    1、 安装Tomcat

    参考Tomcat for window 的安装向|基本直接安装卛_Q注意:安装时会提示输入理用户名和密码Q这是以后会用到的用户名和密码,切记?br />

    2、 安装MySql

    默认安装卛_?br />

    3、 用Tomcat的Web理应用配置数据?br />
    启动Tomcat服务器,打开览器,输入http://localhost:8080/admin/Q其中localhost可能是一台机器的IP或是服务器名UͼQ进入管理界面的登陆面Q这时候请输入原来安装时要求输入的用户名和密码Q登陆到理界面Q?br />

    选择ResourcesQData sourcesq入配置数据源界面,选择Data Source Actions Q?gt;选择Create New Data Source,q入配置详细信息界面Q内容如下:

    JNDI Name: jdbc/mysql
    Data Source URL: jdbc:mysql://192.168.0.16/SUBRDB 
    JDBC Driver Class: org.gjt.mm.mysql.Driver 
    User Name: root
    Password: ********
    Max. Active Connections: 4
    Max. Idle Connections: 2
    Max. Wait for Connection: 500
    Validation Query: 


    要求输入的JNDI Name{信息,其中除了JDBC DriverClass之外Q其他的可以Ҏ(gu)你的需要填写。比如Data Source URL的内容可能是Qjdbc:mysql:// IP或是名称/DataBaseNameQ其中DataBaseName是你的数据库名称QIP是你的数据库的所在的服务器的IP或是名称。最后点击SaveQ?gt;Commit Change.q样你的数据源的基本资料配置一半了?br />

    4、 web.xml?TOMCAT_HOME%\conf\Catalina\localhost下对应你的引用的配置文g修改

    通过文g夹导航到%TOMCAT_HOME%\confQ打开web.xml,?lt;/web-app>的前面添加以下内容:

    <resource-ref>

    <description>DB Connection</description>

    <res-ref-name>jdbc/mysql</res-ref-name>

    <res-type>javax.sql.DataSource</res-type>

    <res-auth>Container</res-auth>

    </resource-ref>


    注意res-ref-name填写的内容要与在上文提到的JNDI Name名称一致。?br />
    通过文g夹导航到%TOMCAT_HOME%\conf\Catalina\localhost下,扑ֈ你的web应用对应?xml文gQ如 ROOT.xmlQƈ在此文g的下d代码Q?br />
    <ResourceLink name="jdbc/mysql" global="jdbc/mysql" type="javax.sql.DataSourcer"/>

    到这里,配置工作基本完成了?br />

    5、 其他注意事?br />
    别忘了JDBC驱动E序mysql-connector-java-3.0.9-stable-bin.jar一定要攄到Tomcat的对应目?你的JDBC驱动可能版比W者高Q不q只要能与所使用的MySql对应可以了Q因为我发现版本太低的JDBC驱动不能支持4.0.*版本的MySQL数据库,攄?TOMCAT_HOME%\common\lib和应用的WEB-INF\lib下。两者有什么不同呢Q其实一看就明白了,common\li是所有的应用都可以用的库文件位|?br />
    重启你的Tomcat服务?br />


    6、 编写测试代?br />
    在应用的目录下徏立一个Test.jsp文gQ代码如下:

    <!doctype html public "-//w3c//dtd html 4.0 transitional//en" 

    "http://www.w3.org/TR/REC-html40/strict.dtd">

    <%@ page import="java.sql.*"%>

    <%@ page import="javax.sql.*"%>

    <%@ page import="javax.naming.*"%>

    <%@ page session="false" %>

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <title></title>

    <% 

    out.print("我的试开?);

    DataSource ds = null;

    try{

    InitialContext ctx=new InitialContext();

    ds=(DataSource)ctx.lookup("java:comp/env/jdbc/mysql");

    Connection conn = ds.getConnection();

    Statement stmt = conn.createStatement();

    //提示Qusers必须是数据库已有的表Q?br />
    //q里的数据库前文提及的Data Source URL配置里包含的数据库?br />
    String strSql = " select * from users";

    ResultSet rs = stmt.executeQuery(strSql);

    while(rs.next()){

    out.print(rs.getString(1)); 

    }

    out.print("我的试l束");

    }

    catch(Exception ex){

    out.print(“出C外,信息??ex.getMessage());

    ex.printStackTrace();

    }

    %>

    </head>

    <body>

    </body>

    </html>


    q行l果Q?br />
    我的试开?2345678我的试l束Q因为我的rs.getString(1) 在数据库是存放12345678


    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=613371



    ]]>
    [收藏]一个关于优化SQL的文?/title><link>http://www.tkk7.com/iKingQu/articles/36467.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Mon, 20 Mar 2006 15:03:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/36467.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/36467.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/36467.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/36467.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/36467.html</trackback:ping><description><![CDATA[ <div id="wqujvhf" class="postText">大家都在讨论关于数据库优化方面的东东Q刚好参与开发了一个数据仓库方面的目Q以下的一点东西算是数据库优化斚w的学?实战的一些心得体会了Q拿出来大家׃n。欢q批评指正阿Q?br /><br />SQL语句Q?br />是对数据?数据)q行操作的惟一途径Q?br />消耗了70%~90%的数据库资源Q独立于E序设计逻辑Q相对于对程序源代码的优化,对SQL语句的优化在旉成本和风险上的代价都很低Q?br />可以有不同的写法Q易学,隄通。?br /><br />SQL优化Q?br />固定的SQL书写习惯Q相同的查询量保持相同Q存储过E的效率较高。?br />应该~写与其格式一致的语句Q包括字母的大小写、标点符受换行的位置{都要一臾b?br /><br />ORACLE优化器: <br />在Q何可能的时候都会对表达式进行评伎ͼq且把特定的语法l构转换成等Ll构Q这么做的原因是 <br />要么l果表达式能够比源表辑ּh更快的速度 <br />要么源表辑ּ只是l果表达式的一个等仯义结构?br />不同的SQLl构有时h同样的操作(例如Q? ANY (subquery) and IN (subquery)Q,ORACLE会把他们映射C个单一的语义结构。?br /><br />1 帔R优化Q?br />帔R的计是在语句被优化时一ơ性完成,而不是在每次执行时。下面是索月薪大?000的的表达式: <br />sal > 24000/12 <br />sal > 2000 <br />sal*12 > 24000 <br />如果SQL语句包括W一U情况,优化器会单地把它转变成第二种。?br />优化器不会简化跨比较符的表辑ּQ例如第三条语句Q鉴于此Q应量写用帔R跟字D|较检索的表达式,而不要将字段|于表达式当中。否则没有办法优化,比如如果sal上有索引Q第一和第二就可以使用Q第三就难以使用。?br /><br />2 操作W优化: <br />优化器把使用LIKE操作W和一个没有通配W的表达式组成的索表辑ּ转换Z个?”操作符表达式。?br />例如Q优化器会把表达式ename LIKE 'SMITH'转换为ename = 'SMITH' <br />优化器只能{换涉及到可变长数据类型的表达式,前一个例子中Q如果ENAME字段的类型是CHAR(10)Q 那么优化器不做Q何{换。?br />一般来讲LIKE比较难以优化。?br /><br />其中Q?br />~~ IN 操作W优化: <br />优化器把使用IN比较W的索表辑ּ替换为等L使用?”和“OR”操作符的检索表辑ּ。?br />例如Q优化器会把表达式ename IN ('SMITH','KING','JONES')替换为?br />ename = 'SMITH' OR ename = 'KING' OR ename = 'JONES‘?br /><br />~~ ANY和SOME 操作W优? <br />优化器将跟随值列表的ANY和SOME索条件用{h(hun)的同{操作符和“OR”组成的表达式替换。?br />例如Q优化器如下所C的W一条语句用W二条语句替换: <br />sal > ANY (:first_sal, :second_sal) <br />sal > :first_sal OR sal > :second_sal <br />优化器将跟随子查询的ANY和SOME索条件{换成由“EXISTS”和一个相应的子查询组成的索表辑ּ。?br />例如Q优化器如下所C的W一条语句用W二条语句替换: <br />x > ANY (SELECT sal FROM emp WHERE job = 'ANALYST') <br />EXISTS (SELECT sal FROM emp WHERE job = 'ANALYST' AND x > sal) <br /><br />~~ ALL操作W优? <br />优化器将跟随值列表的ALL操作W用{h(hun)的?”和“AND”组成的表达式替换。例如: <br />sal > ALL (:first_sal, :second_sal)表达式会被替换ؓQ?br />sal > :first_sal AND sal > :second_sal <br />对于跟随子查询的ALL表达式,优化器用ANY和另外一个合适的比较W组成的表达式替换。例如?br />x > ALL (SELECT sal FROM emp WHERE deptno = 10) 替换为: <br />NOT (x <= ANY (SELECT sal FROM emp WHERE deptno = 10)) <br />接下来优化器会把W二个表辑ּ适用ANY表达式的转换规则转换Z面的表达式: <br />NOT EXISTS (SELECT sal FROM emp WHERE deptno = 10 AND x <= sal) <br /><br />~~ BETWEEN 操作W优? <br />优化器L用?gt;=”和?lt;=”比较符来等L代替BETWEEN操作W。?br />例如Q优化器会把表达式sal BETWEEN 2000 AND 3000用sal >= 2000 AND sal <= 3000来代ѝ?br /><br />~~ NOT 操作W优? <br />优化器L试图化检索条件以消除“NOT”逻辑操作W的影响Q这涉及到“NOT”操作符的消除以及代以相应的比较q算W。?br />例如Q优化器下面的W一条语句用W二条语句代替: <br />NOT deptno = (SELECT deptno FROM emp WHERE ename = 'TAYLOR') <br />deptno <> (SELECT deptno FROM emp WHERE ename = 'TAYLOR') <br />通常情况下一个含有NOT操作W的语句有很多不同的写法Q优化器的{换原则是低쀜NOT”操作符后边的子句尽可能的简单,即可能会ɾl果表达式包含了更多的“NOT”操作符。?br />例如Q优化器如下所C的W一条语句用W二条语句代替: <br />NOT (sal < 1000 OR comm IS NULL) <br />NOT sal < 1000 AND comm IS NOT NULL sal >= 1000 AND comm IS NOT NULL <br /><br />如何~写高效的SQL: <br />当然要考虑sql帔R的优化和操作W的优化啦,另外Q还需要: <br /><br />1 合理的烦引设计: <br />例:表record?20000行,试看在不同的索引下,下面几个SQL的运行情况: <br />语句A <br />SELECT count(*) FROM record <br />WHERE date >'19991201' and date < '19991214‘ and amount >2000 <br /><br />语句B <br />SELECT count(*) FROM record <br />WHERE date >'19990901' and place IN ('BJ','SH') <br /><br />语句C <br />SELECT date,sum(amount) FROM record <br />group by date <br />1 在date上徏有一个非聚集索引 <br />AQ?25U? <br />BQ?27U? <br />CQ?55U? <br />分析Q?br />date上有大量的重复|在非聚集索引下,数据在物理上随机存放在数据页上,在范围查找时Q必L行一ơ表扫描才能扑ֈq一范围内的全部行。?br />2 在date上的一个聚集烦引?br />AQ(14U) <br />BQ(14U) <br />CQ(28U) <br />分析Q?br />在聚集烦引下Q数据在物理上按序在数据页上,重复g排列在一P因而在范围查找Ӟ可以先找到这个范围的h点,且只在这个范围内扫描数据,避免了大范围扫描Q提高了查询速度。?br />3 在placeQdateQamount上的l合索引 <br />AQ(26U) <br />CQ(27U) <br />BQ(< 1U) <br />分析Q?br />q是一个不很合理的l合索引Q因为它的前导列是placeQ第一和第二条SQL没有引用placeQ因此也没有利用上烦引;W三个SQL使用了placeQ且引用的所有列都包含在l合索引中,形成了烦引覆盖,所以它的速度是非常快的。?br />4 在dateQplaceQamount上的l合索引 <br />AQ?< 1U? <br />BQ(< 1U) <br />CQ(11U) <br />分析Q?br />q是一个合理的l合索引。它?yu)date作ؓ前导列,使每个SQL都可以利用烦引,q且在第一和第三个SQL中Ş成了索引覆盖Q因而性能辑ֈ了最优。?br /><br />ȝ1 <br />~省情况下徏立的索引是非聚集索引Q但有时它ƈ不是最佳的Q合理的索引设计要徏立在对各U查询的分析和预上。一般来_ <br />有大量重复倹{且l常有范围查询(between, >,< Q?gt;=,< =Q和order by、group by发生的列Q考虑建立聚集索引Q?br />l 常同时存取多列Q且每列都含有重复值可考虑建立l合索引Q在条g表达式中l常用到的不同D多的列上建立索,在不同值少的列上不要徏立烦引。比如在雇员 表的“性别”列上只有“男”与“女”两个不同|因此无必要建立索引。如果徏立烦引不但不会提高查询效率,反而会严重降低更新速度。?br />l合索引要尽量关键查询形成索引覆盖Q其前导列一定是使用最频繁的列。?br /><br />2 避免使用不兼容的数据cdQ?br />例如float和INt、char和varchar、bINary和varbINary是不兼容的。数据类型的不兼容可能优化器无法执行一些本来可以进行的优化操作。例? <br />SELECT name FROM employee WHERE salary Q?0000 <br />在这条语句中,如salary字段是money型的,则优化器很难对其q行优化,因ؓ60000是个整型数。我们应当在~程时将整型转化成ؓ钱币?而不要等到运行时转化。?br /><br />3 IS NULL 与IS NOT NULLQ?br />不 能用null作烦引,M包含null值的列都不会被包含在烦引中。即使烦引有多列q样的情况下Q只要这些列中有一列含有nullQ该列就会从索引中排 除。也是说如果某列存在空|即对该列徏索引也不会提高性能。Q何在WHERE子句中用is null或is not null的语句优化器是不允 许使用索引的。?br /><br />4 IN和EXISTSQ?br />EXISTS要远比IN的效率高。里面关pdfull table scan和range scan。几乎将所有的IN操作W子查询改写Z用EXISTS的子查询。?br />例子Q?br />语句1 <br />SELECT dname, deptno FROM dept <br />WHERE deptno NOT IN <br />(SELECT deptno FROM emp); <br />语句2 <br />SELECT dname, deptno FROM dept <br />WHERE NOT EXISTS <br />(SELECT deptno FROM emp <br />WHERE dept.deptno = emp.deptno); <br />明显的,2要比1的执行性能好很多?br />因ؓ1中对empq行了full table scan,q是很浪Ҏ(gu)间的操作。而且1中没有用到emp的INdexQ?br />因ؓ没有WHERE子句。?中的语句对empq行的是range scan。?br /><br />5 IN、OR子句怼使用工作表,使烦引失效: <br />如果不生大量重复|可以考虑把子句拆开。拆开的子句中应该包含索引。?br /><br />6 避免或简化排序: <br />应当化或避免对大型表q行重复的排序。当能够利用索引自动以适当的次序生输出时Q优化器避免了排序的步骤。以下是一些媄响因素: <br />索引中不包括一个或几个待排序的列; <br />group by或order by子句中列的次序与索引的次序不一P <br />排序的列来自不同的表。?br />Z避免不必要的排序Q就要正地增徏索引Q合理地合ƈ数据库表Q尽有时可能媄响表的规范化Q但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图化它Q如~小排序的列的范围等。?br /><br />7 消除对大型表行数据的序存取Q?br />在 嵌套查询中Q对表的序存取Ҏ(gu)询效率可能生致命的影响。比如采用顺序存取策略,一个嵌?层的查询Q如果每层都查询1000行,那么q个查询p查询 10亿行数据。避免这U情늚主要Ҏ(gu)是对连接的列进行烦引。例如,两个表:学生表(学号、姓名、年??Q和选课表(学号、课E号、成l)。如果两个 表要做q接Q就要在“学号”这个连接字D上建立索引。?br />q可以用ƈ集来避免序存取。尽在所有的查列上都有烦引,但某些Ş式的WHERE子句优化器用顺序存取。下面的查询强q对orders表执行顺序操作: <br />SELECT Q FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008 <br />虽然在customer_num和order_num上徏有烦引,但是在上面的语句中优化器q是使用序存取路径扫描整个表。因个语句要索的是分ȝ行的集合Q所以应该改为如下语句: <br />SELECT Q FROM orders WHERE customer_num=104 AND order_num>1001 <br />UNION <br />SELECT Q FROM orders WHERE order_num=1008 <br />q样p利用索引路径处理查询。?br /><br />8 避免相关子查询: <br />一个列的标{֐时在L询和WHERE子句中的查询中出玎ͼ那么很可能当L询中的列值改变之后,子查询必重新查询一ơ。查询嵌套层ơ越多,效率低Q因此应当尽量避免子查询。如果子查询不可避免Q那么要在子查询中过滤掉可能多的行。?br /><br />9 避免困难的正规表辑ּQ?br />MATCHES和LIKE关键字支持通配W匹配,技术上叫正规表辑ּ。但q种匚w特别耗费旉。例如:SELECT Q FROM customer WHERE zipcode LIKE ?8_ _ _”?br />即在zipcode字段上徏立了索引Q在q种情况下也q是采用序扫描的方式。如果把语句改ؓSELECT Q FROM customer WHERE zipcode >?8000”,在执行查询时׃利用索引来查询,昄会大大提高速度。?br />另外Q还要避免非开始的子串。例如语句:SELECT Q FROM customer WHERE zipcode[2Q?] >?0”,在WHERE子句中采用了非开始子Ԍ因而这个语句也不会使用索引。?br /><br />10 不充份的q接条gQ?br />例:表card?896行,在card_no上有一个非聚集索引Q表account?91122行,在account_no上有一个非聚集索引Q试看在不同的表q接条g下,两个SQL的执行情况: <br />SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no <br />Q?0U) <br />SQL改ؓQ?br />SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no and a.account_no=b.account_no <br />Q?lt; 1U) <br />分析Q?br />在第一个连接条件下Q最x询方案是account作外层表Qcard作内层表Q利用card上的索引Q其I/Oơ数可由以下公式估算为: <br />外层表account上的22541?Q外层表account?91122?内层表card上对应外层表W一行所要查扄3)=595907ơI/O <br />在第二个q接条g下,最x询方案是card作外层表Qaccount作内层表Q利用account上的索引Q其I/Oơ数可由以下公式估算为: <br />外层表card上的1944?Q外层表card?896?内层表account上对应外层表每一行所要查扄4)= 33528ơI/O <br />可见Q只有充份的q接条gQ真正的最x案才会被执行。?br />多表操作在被实际执行前,查询优化器会Ҏ(gu)q接条gQ列出几l可能的q接Ҏ(gu)q从中找出系l开销最的最x案。连接条件要充䆾考虑带有索引的表、行数多的表Q内外表的选择可由公式Q外层表中的匚w行数*内层表中每一ơ查扄ơ数定Q乘U最ؓ最x案。?br />不可优化的WHERE子句 <br />? <br />下列SQL条g语句中的列都建有恰当的烦引,但执行速度却非常慢Q?br />SELECT * FROM record WHERE substrINg(card_no,1,4)='5378' <br />(13U? <br />SELECT * FROM record WHERE amount/30< 1000 <br />Q?1U) <br />SELECT * FROM record WHERE convert(char(10),date,112)='19991201' <br />Q?0U) <br />分析Q?br />WHERE子句中对列的M操作l果都是在SQLq行旉列计算得到的,因此它不得不q行表搜索,而没有用该列上面的索引Q如果这些结果在查询~译时就能得刎ͼ那么可以被SQL优化器优化,使用索引Q避免表搜烦Q因此将SQL重写成下面这P <br />SELECT * FROM record WHERE card_no like '5378%' <br />Q?lt; 1U) <br />SELECT * FROM record WHERE amount< 1000*30 <br />Q?lt; 1U) <br />SELECT * FROM record WHERE date= '1999/12/01' <br />Q?lt; 1U) <br /><br />11 存储q程中,采用临时表优化查询: <br />例?br />1Q从parven表中按vendor_num的次序读数据Q?br />SELECT part_numQvendor_numQprice FROM parven ORDER BY vendor_num <br />INTO temp pv_by_vn <br />q个语句序读parvenQ?0)Q写一个时表Q?0)Qƈ排序。假定排序的开销?00,d?00c?br />2Q把临时表和vendor表连接,把结果输出到一个时表Qƈ按part_num排序Q?br />SELECT pv_by_vnQ* vendor.vendor_num FROM pv_by_vnQvendor <br />WHERE pv_by_vn.vendor_num=vendor.vendor_num <br />ORDER BY pv_by_vn.part_num <br />INTO TMP pvvn_by_pn <br />DROP TABLE pv_by_vn <br />q 个查询dpv_by_vn(50?Q它通过索引存取vendor?.5万次Q但׃按vendor_numơ序排列Q实际上只是通过索引序地读 vendor表(40Q?=42)Q输出的表每늺95行,?60c写q存取这些页引发5Q?60=800ơ的dQ烦引共d892c?br />3Q把输出和partq接得到最后的l果Q?br />SELECT pvvn_by_pn.Q,part.part_desc FROM pvvn_by_pnQpart <br />WHERE pvvn_by_pn.part_num=part.part_num <br />DROP TABLE pvvn_by_pn <br />q样Q查询顺序地读pvvn_by_pn(160?Q通过索引读part?.5万次Q由于徏有烦引,所以实际上q行1772ơ磁盘读写,优化比例?0?。?br /><br />好了Q搞定。?br />其实sql的优化,各种数据库之间都是互通的?br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=629369</p></div> <img src ="http://www.tkk7.com/iKingQu/aggbug/36467.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-20 23:03 <a href="http://www.tkk7.com/iKingQu/articles/36467.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[收藏]Transact SQL 常用语句以及函数 http://www.tkk7.com/iKingQu/articles/36463.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 14:53:00 GMThttp://www.tkk7.com/iKingQu/articles/36463.htmlhttp://www.tkk7.com/iKingQu/comments/36463.htmlhttp://www.tkk7.com/iKingQu/articles/36463.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/36463.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36463.html阅读全文

    ]]>
    [收藏]SQL优化http://www.tkk7.com/iKingQu/articles/36423.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 20 Mar 2006 12:53:00 GMThttp://www.tkk7.com/iKingQu/articles/36423.htmlhttp://www.tkk7.com/iKingQu/comments/36423.htmlhttp://www.tkk7.com/iKingQu/articles/36423.html#Feedback1http://www.tkk7.com/iKingQu/comments/commentRss/36423.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/36423.html 首先先了解一个SQL语句的执行过E分3? 语法分析(parase)与编?执行,取数?
    1Q?在语法分析与~译?oracle 使用哈希函数为SQL语句在库~存中分配一个SQL?
    首先查语句是否存?若在,则查询数据库字典、检查必ȝ权限?br />若无Q需要语法分析与~译。所以SQL语句存在与内存中Q将减少分析Q编译时间?br />SQL语句的分析与~译占整个语句运行过E的60%的时_SQL优化的目标就是减分析与~译的时_׃n代码?

    查询SQL语句分析与编译的旉Q?br />select * from v$sysstat
    where name in ('parse time cpu','parse time elapsed','parse count (hard)')

    一个SQL语句的响应时?elapsed time )应该是服务时?{待旉.
    服务旉= CPU执行旉.
    {待旉 可以从v$system_event
    select total_waits, total_timeouts, time_waited, average_wait ,event
    from v$system_event
    where event='latch free'
    所以解析一个SQL语句的^均等待时间是"{待旉/parse count" q个值接q?
    通过数据字典v$sqlare,可以查询到频J被分析与编译的SQL语句.应该减少SQL语句的分析与~译的次?

    2: 常用的实体ȝ内存.
    Z减少分析与编译时?可以常用的的实体如: 存储q程,包等,可能驻留在内存区域.
     1)预留内存I间. sql> show parameter shared_pool_reserved_size
           2)频J用的实体ȝ在内存中. 在用DBMS_SHARED_POOLE序包前,必须首先q行pȝ提供的程序包: dbmspool.sql 和prvtpool.plb
     在加载这两个E序包后,自动生成所需的包.
          加蝲: sql> @/u01/app/oracle/product/8.17/rdbms/admin/dbmspool.sql
               sql> @/u01/app/oracle/product/8.17/rdbms/admin/prvtpool.sql
          包DBMS_SHARED_POOL包含以下存储q程.
          dbms_shared_pool.keep 用于实体保存内? dbms_shared_pool.keep(object in varchar2,[type in char default p]);
                                 object 表示参数? type 表示被驻留内存的实体cd;P 表示存储q程,C表示光标,R表示触发?默认P
           
          dbms_shared_pool.unkeep 用于取消被设|进入内存的实体. dbms_shared_pool.unkeep(object in varchar2,[type in char default p]);
                                 object 表示参数? type 表示被驻留内存的实体cd;P 表示存储q程,C表示光标,R表示触发?默认P
         
          dbms_shared_pool.size(minsize in number)

          select name ,type ,source_size+code_size+parsed_size+error_size "total bytes"
          from dba_object_size
          where owner='SCOTT'

    3: 创徏索引.
       select index_name,table_owner, table_name, tablespace_name from all_indexes
      
       select user_indexes.TABLE_NAME, user_indexes.INDEX_NAME,uniqueness, column_name
       from user_ind_columns ,user_indexes
       where user_ind_columns.INDEX_NAME=user_indexes.INDEX_NAME
       and user_ind_columns.TABLE_NAME=user_indexes.TABLE_NAME
       order by user_indexes.TABLE_TYPE,user_indexes.TABLE_NAME,user_indexes.INDEX_NAME,user_ind_columns.COLUMN_POSITION

    4: 创徏聚簇(cluster): 是一l存储在一L有共同列或经怸起用的?被聚的两个表只有一个数据段.聚簇表在存储?在物理层子表合q到父表?q样少了表的连接时?

    5: 创徏哈希索引.
     
    6: SQL优化? Z成本的优化器CBO(cose_based)和基于规则RBO(rule_based)
       sql> show parameter OPTIMIZER_MODE
       可以修改参数文g: initSID.ora,增加: optimizer_Mode={CHOOSE| RULE| FIRST_ROWS|ALL_ROWS}
      all_rows , first_rows(n)Z成本; rule Z规则,chooseZ规则、成本?br />  /*+ ordered*/
      /*+ rule */
      /*+ first_rows(50) */

      /*+ordered star*/
      写发Q?
      alter system flush shared_pool;
    select /*+ rule */ aa from visit

    原文链接:http://www.tkk7.com/yanmin/archive/2006/03/20/36332.html



    ]]>
    [收藏]Tomcat5配置Mysql/Oracle JDBC数据库连接池http://www.tkk7.com/iKingQu/articles/35334.html風向逆轉 - p爪哇風向逆轉 - p爪哇Tue, 14 Mar 2006 18:32:00 GMThttp://www.tkk7.com/iKingQu/articles/35334.htmlhttp://www.tkk7.com/iKingQu/comments/35334.htmlhttp://www.tkk7.com/iKingQu/articles/35334.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/35334.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/35334.html阅读全文

    ]]>
    [收藏]HSQLDB介绍http://www.tkk7.com/iKingQu/articles/35156.html風向逆轉 - p爪哇風向逆轉 - p爪哇Mon, 13 Mar 2006 18:51:00 GMThttp://www.tkk7.com/iKingQu/articles/35156.htmlhttp://www.tkk7.com/iKingQu/comments/35156.htmlhttp://www.tkk7.com/iKingQu/articles/35156.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/35156.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/35156.htmlby jini

    目前E_版本 1.7.1
    下蝲?http://hsqldb.sourceforge.net/

    (1)?
    hsqldb 是由 Tomas Muller ?Hypersonic SQL 後箋开发出来的专案, hsql 已经停止研发? hypersonic db 是纯 java 所开发的资料? 可以透过 jdbc driver 来存? 支援 ANSI-92 标准?SQL 语法, 而且他占的空间很? 大约只有 160K, 拥有快速的资料库引? 也提供了一些工? 例如 web-server, 记忆体查? 及一些管理工?
    他是属於 BSD ?license, 可以自由下蝲, q且可以安装使用在商业品之?

    (2)安装
    当你下蝲了hsqldb_1_7_1.zip, 他解压~到一个目? 我将UC?%HSQLDB_HOME% , 你可以看?hsqldb 下面有这些目?
    - bin
    - build
    - data
    - demo
    - doc
    - lib  - hsqldb.jar
         - servlet.jar
    - src

    最重要的就?hsqldb.jar, 他攑ֈ工作目录下的 lib ?

    (3)使用
    在命令列模式到工作目?
    cmd>java -cp lib/hsqldb.jar org.hsqldb.util.DatabaseManager
    选择 HSQL Database Engine Standalone ( 档案型资料库 )
    Driver : org.hsqldb.jdbcDriver
    URL : jdbc:hsqldb:test
    sa d, 如果该资料库 ( test ) 不存? 他就会徏?
    test.properties ?test.script

    可以直接?fundad.script 加入 SQL 标准语法,
    当程式v来的时? hsqldb 会自动汇?script 中的资料到记忆体之中
    语法?T-SQL 相当, 可参?http://hsqldb.sourceforge.net/doc/hsqlSyntax.html

    (4)l论
    如果你是型单的资料库运? 可以采用q个 opensource
    其?embedded application 的应?
    但是大型资料例如上百万笔, 除非你的 RAM 很大很大,
    否则会导致速度q慢,
    我尝试在我的?sh)?P4-1.8G 512MB 安装 1百万W资?( 每笔 4 栏位 )
    ׃ out of memory
    如果强制 java -mx1024m -ms1024m 也要׃过一时.... @@"
    不过, 他有个很好用的地? 是 bundle ?Applet 之中
    有兴的人可以参考他的范?

    附带一?

    hibernate 中可以采?HSQLDialect 去连l,HSQLDBq有支持分页的sql语句


    PS: 1?nbsp;在hibernate中,使用hsql中,如果讄主键cd用IdenetityQ那么java的field用IntegercdQ不能用Long?BR>      2、目前HSQLDB版本已经升?.8.0.2


    ]]>
    [收藏]Oracle性能调优原则http://www.tkk7.com/iKingQu/articles/33738.html風向逆轉 - p爪哇風向逆轉 - p爪哇Sun, 05 Mar 2006 11:23:00 GMThttp://www.tkk7.com/iKingQu/articles/33738.htmlhttp://www.tkk7.com/iKingQu/comments/33738.htmlhttp://www.tkk7.com/iKingQu/articles/33738.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/33738.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/33738.htmlOracle性能调优原则    
     
    M事情都有它的源头Q要解决问题Q也得从源头开始,影响ORACLE性能的源头非常多Q主要包括如下方?
      数据库的g配置:CPU、内存、网l条?/P>

      1. CPU:在Q何机器中CPU的数据处理能力往往是衡量计机性能的一个标志,q且ORACLE是一个提供ƈ行能力的数据库系l,在CPU斚w的要求就更高了,如果q行队列数目过了CPU处理的数目,性能׃下降Q我们要解决的问题就是要适当增加CPU的数量了Q当然我们还可以需要许多资源的q程KILL?

      2. 内存:衡量机器性能的另外一个指标就是内存的多少了,在ORACLE中内存和我们在徏数据库中的交换区q行数据的交换,L据时Q磁盘I(y)/O必须{待物理I/O操作完成Q在出现ORACLE的内存瓶颈时Q我们第一个要考虑的是增加内存Q由于I/O的响应时间是影响ORACLE性能的主要参敎ͼ我将在这斚wq行详细的讲?/P>

      3. |络条g:NET*SQL负责数据在网l上的来往Q大量的SQL会o|络速度变慢。比?0M的网卡和100的网卡就对NET*SQL有非常明昄影响Q还有交换机、集U器{等|络讑֤的性能对网l的影响很明显,在Q何网l中不要试图?个集U器来将|段互联?/P>

      OS参数的设|?/P>

      下表l出了OS的参数设|及说明QDBA可以Ҏ(gu)实际需要对q些参数q行讄

      内核参数?/P>

      说明

      bufpages

      对bufferI间不按静态分配,采用动态分配,使bufpages值随nbuf一起对bufferI间q行动态分配?/P>

      create_fastlinks

      对HFS文gpȝ允许快速符号链?/P>

      dbc_max_pct

      加大最大动态bufferI间所占物理内存的癑ֈ比,以满_用系l的d命中率的需要?/P>

      dbc_min_pct

      讄最动态bufferI间所占物理内存的癑ֈ?/P>

      desfree

      提高开始交换操作的最低空闲内存下限,保障pȝ的稳定性,防止出现不可预见的系l崩?Crash)?/P>

      fs_async

      允许q行盘异步操作Q提高CPU和磁盘的利用?/P>

      lotsfree

      提高pȝ解除换页操作的空闲内存的上限|保证应用E序有够的可用内存I间?/P>

      maxdsiz

      针对pȝ数据量大的特点,加大最大数据段的大,保证应用的需要?32?

      maxdsiz_64bit

      maximum process data segment size for 64_bit

      Maxssiz

      加大最大堆栈段的大?32_bit)

      maxssiz_64bit

      加大最大堆栈段的大?64_bit)

      Maxtsiz

      提高最大代码段大小Q满_用要?/P>

      maxtsiz_64bit

      原D大,应调?yu)?/P>

      Minfree

      提高停止交换操作的自由内存的上限

      Shmem

      允许q行内存׃nQ以提高内存的利用率

      Shmmax

      讄最大共享内存段的大,完全满目前的需?/P>

      Timeslice

      ׃pȝ的瓶颈主要反映在盘I(y)/O上,因此 降低旉片的大小Q一斚w可避免因盘I(y)/O不畅造成CPU的等待,从而提高了CPU的综合利用率。另一斚w减少了进E的d量?/P>

      unlockable_mem

      提高了不可锁内存的大,使可用于换页和交换的内存I间扩大,用以满pȝ对内存管理的要求?/P>

      用户SQL质量

      以上讲的都是g斚w的东西,在条件有限的条g下,我们可以调整应用E序的SQL质量:

      1. 不要q行全表扫描(Full Table Scan):全表扫描D大量的I/O

      2. 量建好和用好索引:建烦引也是有讲究的,在徏索引Ӟ也不是烦引越多越好,当一个表的烦引达?个以上时QORACLE的性能可能q是改善不了Q因为OLTPpȝ每表过5个烦引即会降低性能Q而且在一个sql 中, Oracle 从不能用超q?5个烦?当我们用到GROUP BY和ORDER BY?ORACLE׃自动Ҏ(gu)据进行排?而ORACLE在INIT.ORA中决定了sort_area_size区的大小,当排序不能在我们l定的排序区完成?ORACLE׃在磁盘中q行排序,也就是我们讲的时表I间中排? q多的磁盘排序将会o free buffer waits 的值变?而这个区间ƈ不只是用于排序的,对于开发h员我提出如下忠告:

      1)、select,update,delete 语句中的子查询应当有规律地查扑ְ?0%的表?如果一个语句查扄行数过总行数的20%,它将不能通过使用索引获得性能上的提高.

      2)、烦引可能生碎?因ؓ记录从表中删除时,相应也从表的索引中删?表释攄I间可以再用,而烦引释攄I间却不能再?频繁q行删除操作的被索引的表,应当阶段性地重徏索引,以避免在索引中造成I间片,影响性能.在许可的条g?也可以阶D|地truncate?truncate命o删除表中所有记?也删除烦引碎?

      3)、在使用索引时一定要按烦引对应字D늚序q行引用?/P>

      4)、用(+)比用NOT IN更有效率?/P>

      降低ORACLE的竞?

      先讲几个ORACLE的几个参敎ͼq几个参数关pdORACLE的竞?

      1)、freelists ?freelist l?他们负责ORACLE的处理表和烦引的I间理;

      2)、pctfree ?pctused:该参数决定了freelists ?freelist l的行ؓQpctfree 和pctused 参数的唯一目的是Z控制块如何在 freelists 中进?/P>

      讄好pctfree ?pctused对块在freelists的移走和d很重要?/P>

      其他参数的设|?/P>

      1)、包括SGA?pȝ全局?:pȝ全局?SGA)是一个分配给Oracle 的包含一?Oracle 实例的数据库的控制信息内存段?/P>

      主要包括数据库高速缓?the database buffer cache)Q?/P>

      重演日志~存(the redo log buffer)Q?/P>

      ׃n?the shared pool)Q?/P>

      数据字典~存(the data dictionary cache)以及其它各方面的信息

      2)、db_block_buffers(数据高速缓冲区)讉Kq的数据都放在这一片内存区域,该参数越大,Oracle在内存中扑ֈ相同数据的可能性就大Q也卛_快了查询速度?/P>

      3)、share_pool_size (SQL׃n~冲?:该参数是库高速缓存和数据字典的高速缓存?/P>

      4)、Log_buffer (重演日志~冲?

      5)、sort_area_size(排序?

      6)、processes (同时q接的进E数)

      7)、db_block_size (数据库块大小):Oracle默认块ؓ2KBQ太了Q因为如果我们有一?KB的数据,?KB块的数据库要?ơ盘Q才能读完,?KB块的数据库只?ơ就d了,大大减少了I/O操作。数据库安装完成后,׃能再改变db_block_size的gQ只能重新徏立数据库q且建库Ӟ要选择手工安装数据库?/P>

      8)、open_links (同时打开的链接数)

      9)、dml_locks

      10)、open_cursors (打开光标?

      11)、dbwr_io_slaves (后台写进E数)



    ]]>
    [收藏]JDBC入门pd专题讲http://www.tkk7.com/iKingQu/articles/33721.html風向逆轉 - p爪哇風向逆轉 - p爪哇Sun, 05 Mar 2006 07:52:00 GMThttp://www.tkk7.com/iKingQu/articles/33721.htmlhttp://www.tkk7.com/iKingQu/comments/33721.htmlhttp://www.tkk7.com/iKingQu/articles/33721.html#Feedback0http://www.tkk7.com/iKingQu/comments/commentRss/33721.htmlhttp://www.tkk7.com/iKingQu/services/trackbacks/33721.html阅读全文

    ]]>
    [收藏]JDBCq接各种数据库经验技巧集?/title><link>http://www.tkk7.com/iKingQu/articles/33709.html</link><dc:creator>風向逆轉 - p爪哇</dc:creator><author>風向逆轉 - p爪哇</author><pubDate>Sun, 05 Mar 2006 07:14:00 GMT</pubDate><guid>http://www.tkk7.com/iKingQu/articles/33709.html</guid><wfw:comment>http://www.tkk7.com/iKingQu/comments/33709.html</wfw:comment><comments>http://www.tkk7.com/iKingQu/articles/33709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/iKingQu/comments/commentRss/33709.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/iKingQu/services/trackbacks/33709.html</trackback:ping><description><![CDATA[     摘要: JDBC q接各种数据库经验技巧集? Java 数据库连接( JDBC Q由一l用 Java ~程语言~写的类和接口组成? JDBC 为工? / ...  <a href='http://www.tkk7.com/iKingQu/articles/33709.html'>阅读全文</a><img src ="http://www.tkk7.com/iKingQu/aggbug/33709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/iKingQu/" target="_blank">風向逆轉 - p爪哇</a> 2006-03-05 15:14 <a href="http://www.tkk7.com/iKingQu/articles/33709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://oakuu.com" target="_blank">þֹۺ޾Ʒ</a>| <a href="http://msjdyd.com" target="_blank">vƬ߹ۿ</a>| <a href="http://papapa97.com" target="_blank">Ļһ</a>| <a href="http://htsp777.com" target="_blank">õ߳</a>| <a href="http://41xjj.com" target="_blank">þþþ޾ƷӰ</a>| <a href="http://cswsfz.com" target="_blank">޾Ʒþþþϼ</a>| <a href="http://xzgfbxg.com" target="_blank">һƵ </a>| <a href="http://5r7b.com" target="_blank">ĻһԾ</a>| <a href="http://zzttt04.com" target="_blank">ƷһƵ</a>| <a href="http://zkqzdq.com" target="_blank">Ƶѹۿ97 </a>| <a href="http://tha2008.com" target="_blank">Ʒר벻</a>| <a href="http://sxhnyl.com" target="_blank">ƬվŮ</a>| <a href="http://yy885.com" target="_blank">޾ƷƬ</a>| <a href="http://pgb168.com" target="_blank">avרavëƬ</a>| <a href="http://aaa99999.com" target="_blank">ƷѸ</a>| <a href="http://v1s3u5.com" target="_blank">޹Ʒþþѿ</a>| <a href="http://u6u6u6.com" target="_blank">ɫaѿ</a>| <a href="http://yangguang882.com" target="_blank">˳վ߿</a>| <a href="http://www5g9.com" target="_blank">޹ᆱƷԲ߹ۿ </a>| <a href="http://6nn5.com" target="_blank">һѹۿ </a>| <a href="http://10242016.com" target="_blank">޴˽</a>| <a href="http://binz132.com" target="_blank">aɫëƬѲƵ</a>| <a href="http://15831883389.com" target="_blank">avtt</a>| <a href="http://51ykz.com" target="_blank">þ޾Ʒվ</a>| <a href="http://xvwenyue.com" target="_blank">һѹۿƵwww</a>| <a href="http://hbqueena.com" target="_blank">þþþƷ</a>| <a href="http://6123fa.com" target="_blank">9ȾƷѹۿƵ</a>| <a href="http://www132126.com" target="_blank">߹ۿ</a>| <a href="http://jioupin.com" target="_blank">Ȼר</a>| <a href="http://sao350.com" target="_blank">99һ</a>| <a href="http://fuzhiwushu.com" target="_blank">޾ѡ߹ۿ</a>| <a href="http://lyjhjx.com" target="_blank">ƷĻѹۿҹ</a>| <a href="http://56aaaa.com" target="_blank">޾Ʒ91רֻ</a>| <a href="http://1777000.com" target="_blank">޾ƷŮþþþ</a>| <a href="http://lyaa17.com" target="_blank">ѿٸƵ</a>| <a href="http://nzzys.com" target="_blank">ASS츾ëPICS</a>| <a href="http://xin-matai.com" target="_blank">þþþþþƷѿSSS</a>| <a href="http://billtsssrvp.com" target="_blank">޹˳߹ۿ69վ</a>| <a href="http://ri9999.com" target="_blank">һƬaѲſ</a>| <a href="http://miya863.com" target="_blank">һӰԺ </a>| <a href="http://ttooyuyu.com" target="_blank">avһ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>