﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-java fans-文章分类-数据库学习</title><link>http://www.blogjava.net/jlin/category/14019.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 22 Nov 2010 10:18:44 GMT</lastBuildDate><pubDate>Mon, 22 Nov 2010 10:18:44 GMT</pubDate><ttl>60</ttl><item><title>关于Java连接db2 的问题</title><link>http://www.blogjava.net/jlin/articles/338678.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Mon, 22 Nov 2010 05:30:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/338678.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/338678.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/338678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/338678.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/338678.html</trackback:ping><description><![CDATA[//驱动的问题 <br />
&nbsp;&nbsp;&nbsp; Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); <br />
Connection con = DriverManager.getConnection("jdbc:db2://133.64.37.1:50000/CHURNDB", "test", "test"); <br />
<br />
<br />
DB2有几种jdbc驱动，jdbc-url分别如下： <br />
jdbc:db2:localhost:db2test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COM.ibm.db2.jdbc.net.DB2Driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type3&nbsp; db2java.zip <br />
jdbc:db2:db2test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COM.ibm.db2.jdbc.app.DB2Driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type2&nbsp; db2java.zip <br />
jdbc:db2://localhost:50000/db2test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; com.ibm.db2.jcc.DB2Driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type4 db2jcc.jar <br />
<br />
另外用type4时 数据库必须将codeset设置成utf-8 <br />
否则查询时会抛出com.ibm.db2.jcc.b.DisconnectException: encoding not supported!!异常 <br />
<br />
今天犯了错误，弄混了写法，希望没人再犯同样的错。 <br />
我的版本是 udb8.1。 <br />
<br />
<br />
<br />
---------------------------------------------------------------------- <br />
<br />
/**了解基础情况**/ <br />
对于Java程序员而言，DB2 提供了两种应用程序编程接口（API）：JDBC 和 SQLJ。 <br />
<br />
JDBC: <br />
&nbsp; JDBC 驱动程序分为旧的／CLI 驱动程序&lt;db2java.zip&gt;和新的通用 JDBC 驱动程序（Universal JDBC Driver）&lt;db2jcc.jar&gt;。 <br />
&nbsp; JDBC 是一个与供应商无关的动态 SQL 接口，该接口通过标准化的 Java 方法向您的应用程序提供数据访问。 <br />
&nbsp; JDBC 类似于 DB2 CLI，因为您无须预编译应用程序代码，也无须将软件包绑定到 DB2 数据库。 <br />
&nbsp; 作为一个与供应商无关的标准，JDBC 应用程序提供了更多的可移植性—这是当今异构业务基础设施所必需的优点。 <br />
&nbsp; 在执行 JDBC 应用程序期间，驱动程序将针对当前连接的 DB2 数据库服务器验证 SQL 语句。 <br />
&nbsp; 访问期间的任何问题都会作为 Java 异常与相应的 SQLSTATE 和 SQLCODE 一起报告给应用程序。 <br />
SQLJ: <br />
&nbsp; SQLJ 是一个用于从 Java 应用程序进行数据访问的标准开发模型。 <br />
&nbsp; SQLJ API 是在 SQL 1999 规范中定义的。 <br />
&nbsp; <br />
新的通用 JDBC 驱动程序在一个实现中同时为 JDBC 和 SQLJ API 提供了支持。 <br />
JDBC 和 SQLJ 可以在同一个应用程序中互操作。 <br />
SQLJ 提供了独特的使用静态 SQL 语句进行开发以及在 DB2 包级别控制访问的能力。 <br />
<br />
/**JDBC连接方式分析**/ <br />
JDBC 驱动程序体系结构分为四种类型：Type1,Type2,Type3,Type4。 <br />
<br />
Type1： <br />
&nbsp; 驱动程序基于 JDBC-ODBC 桥。 <br />
&nbsp; 因此 ODBC 驱动程序可以与此类 JDBC 驱动程序（由 Sun 提供）结合起来使用。 <br />
&nbsp; IBM 不支持 Type 1 驱动程序，因此它不是推荐的环境。 <br />
<br />
<br />
Type2: <br />
&nbsp;&nbsp; 驱动程序依靠特定于操作系统的库（共享库）来与 RDBMS 通信。 <br />
&nbsp;&nbsp; 应用程序将装入这种 JDBC 驱动程序，而驱动程序将使用共享库来与 DB2 服务器通信。 <br />
&nbsp;&nbsp; DB2 UDB for Linux, UNIX和 WindowsV8.1 提供了两种不同的 Type 2 驱动程序： <br />
&nbsp;&nbsp; &lt;1&gt; 旧的／CLI JDBC 驱动程序在文件db2java.zip中提供。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 其实现包名称为COM.ibm.db2.jdbc.app.DB2Driver。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 该驱动程序目前已被用于进行 J2EE 认证。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 其别名&#8220;app 驱动程序&#8221;源自于一种观念及其包名称， <br />
&nbsp;&nbsp;&nbsp;&nbsp; 这种观念就是：此驱动程序将通过远程数据库的本地 DB2 UDB 客户机执行本地连接。 <br />
&nbsp;&nbsp; &lt;2&gt; 通用 JDBC 驱动程序在文件db2jcc.jar中提供。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 其实现包名称为com.ibm.db2.jcc.DB2Driver。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 此驱动程序是 DB2 UDB for Linux, UNIX 和 Windows V8.1 中的新功能。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 在最初的实现（V8.1）中，此驱动程序用于使用 Type 4 驱动程序体系结构与 DB2 服务器进行直接的 Java 连接。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 在 DB2 V8.1.2 中，您可以在 Type 2 体系结构中使用此驱动程序。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 在 Type 2 体系结构中使用此驱动程序的一个主要原因是为了本地应用程序性能和分布式事务支持。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 通用 JDBC Type 2 驱动程序分别使用com.ibm.db2.jcc.DB2XADataSource和com.ibm.db2.jcc.DB2ConnectionPoolDataSource来支持分布式事务和连接池。 <br />
<br />
&nbsp; 注：在将来的版本中不会对旧的／CLI Type 2 驱动程序进行增强。 <br />
<br />
<br />
Type3: <br />
&nbsp;&nbsp; 驱动程序是一种纯 Java 实现，它必须与 DB2 JDBC Applet 服务器（DB2 JDBC Applet Server）通信才能访问 DB2 数据。 <br />
&nbsp;&nbsp; 此类驱动程序旨在使 Java applet 能访问 DB2 数据源。 <br />
&nbsp;&nbsp; 常被称作&#8220;网络（net）驱动程序&#8221;，它是根据其包名COM.ibm.db2.jdbc.net命名的。DB2 V8.1 支持网络驱动程序，可以将其用于 JDBC 应用程序。 <br />
&nbsp;&nbsp; 要求db2java.zip驱动程序总是处于与 DB2 Applet 服务器相同的维护级别。 <br />
&nbsp;&nbsp; 如果驱动程序在 applet 内使用，这就不是一个问题，因为浏览器会在应用程序执行期间下载相应的db2java.zip文件。 <br />
&nbsp;&nbsp; 许多客户使用 Type3 驱动程序而不是 Type2 驱动程序，以避免必需的 DB2 客户机安装和必需的DB2 CATALOG DATABASE命令，后者用于创建使用旧的／CLI 驱动程序进行 Type 2 连接所必需的数据库目录信息。 <br />
&nbsp;&nbsp; 目前，WebSphere Application Server 和其它 J2EE 服务器不支持 IBM Type 3 驱动程序，因为该驱动程序不支持分布式事务（JTA）。 <br />
&nbsp;&nbsp; 将来的版本不会对 Type 3 驱动程序进行增强。 <br />
<br />
&nbsp;&nbsp; 鼓励使用通用 JDBC Type 4 驱动程序来替代 Type 3 驱动程序。 <br />
<br />
<br />
Type4: <br />
&nbsp; 驱动程序是仅用于 Java 的 JDBC 驱动程序，它直接连接到数据库服务器。 <br />
&nbsp; DB2 UDB for Linux, UNIX 和 Windows V8.1 引入了称为&#8220;通用 JDBC 驱动程序（Universal JDBC driver）&#8221;的 Type 4 驱动程序。 <br />
&nbsp; 通用 JDBC 驱动程序在文件db2jcc.jar中提供。 <br />
&nbsp; 其实现包名为com.ibm.db2.jcc.DB2Driver。 <br />
&nbsp; 请注意，通用 Type 2 和通用 Type 4 驱动程序具有相同的实现类名称。 <br />
&nbsp; 有两种方法可以区别 DB2 在内部将实例化哪个驱动程序： <br />
&nbsp; 使用连接特性来确定连接是否使用共享库（Type2），或者驱动程序是否会启动来自 Java 应用程序的直接连接（Type4）。 <br />
<br />
<br />
重要：就 DB2 UDB V8.1.2 而言，通用 JDBC 驱动程序要求 CLASSPATH 中有许可证 JAR 文件和db2jcc.jar文件。 <br />
以下是所需的许可证 JAR 文件： <br />
&nbsp; Cloudscape Network Server V5.1：db2jcc_license_c.jar <br />
&nbsp; DB2 UDB V8 for Linux, UNIX 和 Windows 服务器：db2jcc_license_su.jar <br />
&nbsp; DB2 UDB for iSeries and z/OS 服务器（与 DB2 Connect 和 DB2 Enterprise Server Edition 一起提供）：db2jcc_license_cisuz.jar <br />
<br />
<br />
<br />
驱动程序类型：db2java.zip, db2jcc.jar <br />
注意：假如你使用db2java.zip,且web服务器使用Tomcat的话,请将db2java.zip改名为db2java.jar,最好将zip解压再用jar命令打包,直接改文件类型也行(呵呵,按照jar文件严格意义上来讲这是不符合文法的&lt;少了描述性文件:MANIFEST.MF&gt;,能用就行) <br />
&nbsp;&nbsp; 还有一般情况下：就是使用 db2java.zip的话需要安装db2客户端, 使用db2jcc.jar是通过网络直接来连接的无需安装db2客户端(假如用在type2上还是要装客户端的) <br />
<br />
type2: <br />
使用&lt;db2java.zip&gt;: <br />
&nbsp; jdbc.driverClassName=COM.ibm.db2.jdbc.app.DB2Driver <br />
&nbsp;&nbsp;&nbsp; jdbc.url=jdbc:db2:dataBaseName <br />
&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp; 假如你的工具使用的是myeclipse且使用的是tomcat plugin的话，请将db2jdbc.dll 拷贝到 %JAVA_HOME%/bin下，否则不行地啦 <br />
&nbsp;&nbsp; &lt;是不是其他类型的使用db2java.zip驱动也有这个问题呢，不知道，没试过，有空试一下&gt; <br />
&nbsp;&nbsp; <br />
&nbsp; 使用&lt;db2jcc.jar&gt;: <br />
&nbsp;&nbsp; jdbc.driverClassName=com.ibm.db2.jcc.DB2Driver <br />
&nbsp;&nbsp; jdbc.url=jdbc:db2:dataBaseName <br />
&nbsp; <br />
type3: <br />
驱动：db2java.zip <br />
jdbc.driverClassName=COM.ibm.db2.jdbc.net.DB2Driver <br />
&nbsp; jdbc.url=jdbc:db2://ip:6789/DBNAME <br />
&nbsp; 注意：要在数据库上执行 db2jstrt 6789 （这句启动了db2jd进程，6789是默认的服务器侦听jdbc2连接的端口，也可以设置成另外的任意不冲突的端口。） <br />
&nbsp; <br />
type4: <br />
驱动:db2jcc.jar <br />
数据库字符集必须设置为utf-8 <br />
&nbsp; jdbc.driverClassName=com.ibm.db2.jcc.DB2Driver <br />
&nbsp; jdbc.url=jdbc:db2://ip:port/DBNAME 
<img src ="http://www.blogjava.net/jlin/aggbug/338678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-11-22 13:30 <a href="http://www.blogjava.net/jlin/articles/338678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle SQL性能优化(转)</title><link>http://www.blogjava.net/jlin/articles/334529.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Tue, 12 Oct 2010 03:59:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/334529.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/334529.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/334529.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/334529.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/334529.html</trackback:ping><description><![CDATA[<p>&nbsp; 我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习、摘录、并汇总部分资料与大家分享！ <br />
（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选择最有效率的表名顺序(只在基于规则的优化器中有效)：<br />
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名，FROM子句中写在最后的表(基础表 driving table)将被最先处理，在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.<br />
（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE子句中的连接顺序．：<br />
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.<br />
（3）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT子句中避免使用 &#8216; * &#8216;：<br />
ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间<br />
（4）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 减少访问数据库的次数：<br />
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等；<br />
（5）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200<br />
（6）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用DECODE函数来减少处理时间：<br />
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.<br />
（7）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 整合简单,无关联的数据库访问：<br />
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)<br />
（8）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 删除重复记录：<br />
最高效的删除重复记录方法 ( 因为使用了ROWID)例子：<br />
DELETE&nbsp; FROM&nbsp; EMP E&nbsp; WHERE&nbsp; E.ROWID &gt; (SELECT MIN(X.ROWID) <br />
FROM&nbsp; EMP X&nbsp; WHERE&nbsp; X.EMP_NO = E.EMP_NO);<br />
（9）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用TRUNCATE替代DELETE：<br />
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)<br />
（10） 尽量多使用COMMIT：<br />
只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: <br />
COMMIT所释放的资源: <br />
a. 回滚段上用于恢复数据的信息. <br />
b. 被程序语句获得的锁 <br />
c. redo log buffer 中的空间 <br />
d. ORACLE为管理上述3种资源中的内部花费<br />
（11） 用Where子句替换HAVING子句：<br />
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中，on是最先执行，where次之，having最后，因为on是先把不符合条件的记录过滤后才进行统计，它就可以减少中间运算要处理的数据，按理说应该速度是最快的，where也应该比having快点的，因为它过滤数据后才进行sum，在两个表联接时才用on的，所以在一个表的时候，就剩下where跟having比较了。在这单表查询统计的情况下，如果要过滤的条件没有涉及到要计算字段，那它们的结果是一样的，只是where可以使用rushmore技术，而having就不能，在速度上后者要慢如果要涉及到计算的字段，就表示在没计算之前，这个字段的值是不确定的，根据上篇写的工作流程，where的作用时间是在计算之前就完成的，而having就是在计算后才起作用的，所以在这种情况下，两者的结果会不同。在多表联接查询时，on比where更早起作用。系统首先根据各个表之间的联接条件，把多个表合成一个临时表后，再由where进行过滤，然后再计算，计算完后再由having进行过滤。由此可见，要想过滤条件起到正确的作用，首先要明白这个条件应该在什么时候起作用，然后再决定放在那里<br />
（12） 减少对表的查询：<br />
在含有子查询的SQL语句中,要特别注意减少对表的查询.例子：<br />
&nbsp;&nbsp;&nbsp;&nbsp; SELECT&nbsp; TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT<br />
TAB_NAME,DB_VER FROM&nbsp; TAB_COLUMNS&nbsp; WHERE&nbsp; VERSION = 604)<br />
（13） 通过内部函数提高SQL效率.：<br />
复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的<br />
（14） 使用表的别名(Alias)：<br />
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.<br />
（15） 用EXISTS替代IN、用NOT EXISTS替代NOT IN：<br />
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.<br />
例子：<br />
（高效）SELECT * FROM&nbsp; EMP (基础表)&nbsp; WHERE&nbsp; EMPNO &gt; 0&nbsp; AND&nbsp; EXISTS (SELECT &#8216;X'&nbsp; FROM DEPT&nbsp; WHERE&nbsp; DEPT.DEPTNO = EMP.DEPTNO&nbsp; AND&nbsp; LOC = &#8216;MELB')<br />
(低效)SELECT&nbsp; * FROM&nbsp; EMP (基础表)&nbsp; WHERE&nbsp; EMPNO &gt; 0&nbsp; AND&nbsp; DEPTNO IN(SELECT DEPTNO&nbsp; FROM&nbsp; DEPT&nbsp; WHERE&nbsp; LOC = &#8216;MELB')<br />
（16） 识别'低效执行'的SQL语句：<br />
虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法：<br />
SELECT&nbsp; EXECUTIONS , DISK_READS, BUFFER_GETS, <br />
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, <br />
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, <br />
SQL_TEXT <br />
FROM&nbsp; V$SQLAREA <br />
WHERE&nbsp; EXECUTIONS&gt;0 <br />
AND&nbsp; BUFFER_GETS &gt; 0 <br />
AND&nbsp; (BUFFER_GETS-DISK_READS)/BUFFER_GETS &lt; 0.8 <br />
ORDER BY&nbsp; 4 DESC;<br />
（17） 用索引提高效率：<br />
索引是表的一个概念部分,用来提高检索数据的效率，ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率. 虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引是有必要的.：<br />
ALTER&nbsp; INDEX &lt;INDEXNAME&gt; REBUILD &lt;TABLESPACENAME&gt;<br />
（18） 用EXISTS替换DISTINCT：<br />
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 例子：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (低效): <br />
SELECT&nbsp; DISTINCT&nbsp; DEPT_NO,DEPT_NAME&nbsp; FROM&nbsp; DEPT D , EMP E <br />
WHERE&nbsp; D.DEPT_NO = E.DEPT_NO <br />
(高效): <br />
SELECT&nbsp; DEPT_NO,DEPT_NAME&nbsp; FROM&nbsp; DEPT D&nbsp; WHERE&nbsp; EXISTS ( SELECT &#8216;X' <br />
FROM&nbsp; EMP E&nbsp; WHERE E.DEPT_NO = D.DEPT_NO);<br />
（19） sql语句用大写的；因为oracle总是先解析sql语句，把小写的字母转换成大写的再执行<br />
（20） 在java代码中尽量少用连接符&#8220;＋&#8221;连接字符串！<br />
（21） 避免在索引列上使用NOT 通常，　<br />
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE&#8221;遇到&#8221;NOT,他就会停止使用索引转而执行全表扫描.<br />
（22） 避免在索引列上使用计算．<br />
WHERE子句中，如果索引列是函数的一部分．优化器将不使用索引而使用全表扫描． <br />
举例: <br />
低效： <br />
SELECT &#8230; FROM&nbsp; DEPT&nbsp; WHERE SAL * 12 &gt; 25000; <br />
高效: <br />
SELECT &#8230; FROM DEPT WHERE SAL &gt; 25000/12;<br />
（23） 用&gt;=替代&gt;<br />
高效: <br />
SELECT * FROM&nbsp; EMP&nbsp; WHERE&nbsp; DEPTNO &gt;=4 <br />
低效: <br />
SELECT * FROM EMP WHERE DEPTNO &gt;3 <br />
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.<br />
（24） 用UNION替换OR (适用于索引列)<br />
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. <br />
高效: <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE LOC_ID = 10 <br />
UNION <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE REGION = &#8220;MELBOURNE&#8221; <br />
低效: <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE LOC_ID = 10 OR REGION = &#8220;MELBOURNE&#8221; <br />
如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面.<br />
（25） 用IN来替换OR&nbsp; <br />
这是一条简单易记的规则，但是实际的执行效果还须检验，在ORACLE8i下，两者的执行路径似乎是相同的．　<br />
低效: <br />
SELECT&#8230;. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30 <br />
高效 <br />
SELECT&#8230; FROM LOCATION WHERE LOC_IN&nbsp; IN (10,20,30);<br />
（26） 避免在索引列上使用IS NULL和IS NOT NULL<br />
避免在索引中使用任何可以为空的列，ORACLE将无法使用该索引．对于单列索引，如果列包含空值，索引中将不存在此记录. 对于复合索引，如果每个列都为空，索引中同样不存在此记录.　如果至少有一个列不为空，则记录存在于索引中．举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值（123,null）的记录(插入). 然而如果所有的索引列都为空，ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.<br />
低效: (索引失效) <br />
SELECT &#8230; FROM&nbsp; DEPARTMENT&nbsp; WHERE&nbsp; DEPT_CODE IS NOT NULL; <br />
高效: (索引有效) <br />
SELECT &#8230; FROM&nbsp; DEPARTMENT&nbsp; WHERE&nbsp; DEPT_CODE &gt;=0;<br />
（27） 总是使用索引的第一个列：<br />
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则，当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引<br />
（28） 用UNION-ALL 替换UNION ( 如果有可能的话)：<br />
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是，UNION ALL 将重复输出两个结果集合中相同记录. 因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量<br />
低效： <br />
SELECT&nbsp; ACCT_NUM, BALANCE_AMT <br />
FROM&nbsp; DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
UNION <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
高效: <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
UNION ALL <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95'<br />
（29） 用WHERE替代ORDER BY：<br />
ORDER BY 子句只在两种严格的条件下使用索引. <br />
ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. <br />
ORDER BY中所有的列必须定义为非空. <br />
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.<br />
例如: <br />
表DEPT包含以下列: <br />
DEPT_CODE PK NOT NULL <br />
DEPT_DESC NOT NULL <br />
DEPT_TYPE NULL<br />
低效: (索引不被使用) <br />
SELECT DEPT_CODE FROM&nbsp; DEPT&nbsp; ORDER BY&nbsp; DEPT_TYPE <br />
高效: (使用索引) <br />
SELECT DEPT_CODE&nbsp; FROM&nbsp; DEPT&nbsp; WHERE&nbsp; DEPT_TYPE &gt; 0<br />
（30） 避免改变索引列的类型.:<br />
当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. <br />
假设 EMPNO是一个数值类型的索引列. <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE&nbsp; EMPNO = &#8216;123' <br />
实际上,经过ORACLE类型转换, 语句转化为: <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE&nbsp; EMPNO = TO_NUMBER(&#8216;123') <br />
幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. <br />
现在,假设EMP_TYPE是一个字符类型的索引列. <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE EMP_TYPE = 123 <br />
这个语句被ORACLE转换为: <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERETO_NUMBER(EMP_TYPE)=123 <br />
因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型<br />
（31） 需要当心的WHERE子句:<br />
某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. <br />
在下面的例子里, (1)&#8216;!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) &#8216;||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) &#8216;+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.<br />
（32） a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高. <br />
b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!<br />
（33） 避免使用耗费资源的操作:<br />
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 <br />
执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强<br />
（34） 优化GROUP BY:<br />
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多.<br />
低效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP <br />
GROUP JOB <br />
HAVING JOB = &#8216;PRESIDENT' <br />
OR JOB = &#8216;MANAGER' <br />
高效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP <br />
WHERE JOB = &#8216;PRESIDENT' <br />
OR JOB = &#8216;MANAGER' <br />
GROUP JOB</p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/fuwei2241/archive/2006/09/06/1185198.aspx</p>
<img src ="http://www.blogjava.net/jlin/aggbug/334529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-10-12 11:59 <a href="http://www.blogjava.net/jlin/articles/334529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle中的BLOB和CLOB读取</title><link>http://www.blogjava.net/jlin/articles/328130.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Fri, 06 Aug 2010 06:20:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/328130.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/328130.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/328130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/328130.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/328130.html</trackback:ping><description><![CDATA[<h1>一、区别和定义</h1>
<p><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>LONG:</strong> 可变长的<font color="#993300">字符串</font>数据，最长2G，LONG具有VARCHAR2列的特性，可以存储长文本一个表中最多一个LONG列<br />
　　<strong>LONG RAW:</strong> 可变长<font color="#993300">二进制</font>数据，最长2G<br />
　　<strong>CLOB:</strong>&nbsp; <span><font color="#ff9900">字符大对象<font size="+0">Clob </font></font></span>用来存储单字节的<font color="#993300">字符</font>数据<br />
　　<strong>NCLOB:</strong> 用来存储多字节的<font color="#993300">字符</font>数据<br />
　　<strong>BLOB:</strong> 用于存储<font color="#993300">二进制</font>数据<br />
　　<strong>BFILE:</strong> 存储在文件中的<font color="#993300">二进制</font>数据，这个文件中的数据只能被只读访。但该文件不包含在数据库内。</font></p>
<p><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bfile字段实际的文件存储在文件系统中,字段中存储的是文件定位指针.bfile对oracle来说是只读的,也不参与事务性控制和数据恢复. <br />
　　<br />
　　CLOB，NCLOB，BLOB都是内部的<font color="#993300">LOB(Large Object)</font>类型，最长4G，没有LONG只能有一列的限制 </font></p>
<p><font size="2">　　要保存图片、文本文件、Word文件各自最好用哪种数据类型?<br />
　　--BLOB最好，LONG　RAW也不错，但Long是oracle将要废弃的类型，因此建议用BLOB。</font></p>
<p><font size="2"></p>
<h1>二、操作 </h1>
<h3>1、 get</h3>
<p><font size="2"></p>
<h5>CLOB</h5>
<p>&nbsp;</p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//获得数据库连接 </span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;ConnectionFactory.getConnection(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Statement&nbsp;st&nbsp;=&nbsp;con.createStatement(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//不需要&#8220;for&nbsp;update&#8221; </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;st.executeQuery(</span><span class="string">"select&nbsp;CLOBATTR&nbsp;from&nbsp;TESTCLOB&nbsp;where&nbsp;ID=1"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(rs.next()) &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.sql.Clob&nbsp;clob&nbsp;=&nbsp;rs.getClob(</span><span class="string">"CLOBATTR"</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reader&nbsp;inStream&nbsp;=&nbsp;clob.getCharacterStream(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">char</span><span>[]&nbsp;c&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">char</span><span>[(</span><span class="keyword">int</span><span>)&nbsp;clob.length()]; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inStream.read(c); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//data是读出并需要返回的数据，类型是String </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;String(c); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inStream.close(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;inStream.close(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.close(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>&nbsp;</p>
<h5>BLOB</h5>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//获得数据库连接 </span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;ConnectionFactory.getConnection(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Statement&nbsp;st&nbsp;=&nbsp;con.createStatement(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//不需要&#8220;for&nbsp;update&#8221; </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;st.executeQuery(</span><span class="string">"select&nbsp;BLOBATTR&nbsp;from&nbsp;TESTBLOB&nbsp;where&nbsp;ID=1"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(rs.next()) &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.sql.Blob&nbsp;blob&nbsp;=&nbsp;rs.getBlob(</span><span class="string">"BLOBATTR"</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;inStream&nbsp;=&nbsp;blob.getBinaryStream(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//data是读出并需要返回的数据，类型是byte[] </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">byte</span><span>[input.available()]; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inStream.read(data); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inStream.close(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;inStream.close(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;con.close(); &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>&nbsp;</p>
<h3>2、 put</h3>
<h5>CLOB</h5>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//获得数据库连接 </span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;ConnectionFactory.getConnection(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Statement&nbsp;st&nbsp;=&nbsp;con.createStatement(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//插入一个空对象empty_clob() </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;st.executeUpdate(</span><span class="string">"insert&nbsp;into&nbsp;TESTCLOB&nbsp;(ID,&nbsp;NAME,&nbsp;CLOBATTR)&nbsp;values&nbsp;(1,&nbsp;"</span><span>thename</span><span class="string">",&nbsp;empty_clob())"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//锁定数据行进行更新，注意&#8220;for&nbsp;update&#8221;语句 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;st.executeQuery(</span><span class="string">"select&nbsp;CLOBATTR&nbsp;from&nbsp;TESTCLOB&nbsp;where&nbsp;ID=1&nbsp;for&nbsp;update"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(rs.next()) &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//得到java.sql.Clob对象后强制转换为oracle.sql.CLOB </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oracle.sql.CLOB&nbsp;clob&nbsp;=&nbsp;(oracle.sql.CLOB)&nbsp;rs.getClob(</span><span class="string">"CLOBATTR"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Writer&nbsp;outStream&nbsp;=&nbsp;clob.getCharacterOutputStream(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//data是传入的字符串，定义：String&nbsp;data </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">char</span><span>[]&nbsp;c&nbsp;=&nbsp;data.toCharArray(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outStream.write(c,&nbsp;</span><span class="number">0</span><span>,&nbsp;c.length); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;outStream.flush(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;outStream.close(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.close(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span> </li>
</ol>
</div>
<div class="code_title">
<div class="code_title">
<div class="code_title">BLOB</div>
<div class="code_title">
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//获得数据库连接 </span><span>&nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;ConnectionFactory.getConnection(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;Statement&nbsp;st&nbsp;=&nbsp;con.createStatement(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//插入一个空对象empty_blob() </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;st.executeUpdate(</span><span class="string">"insert&nbsp;into&nbsp;TESTBLOB&nbsp;(ID,&nbsp;NAME,&nbsp;BLOBATTR)&nbsp;values&nbsp;(1,&nbsp;"</span><span>thename</span><span class="string">",&nbsp;empty_blob())"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//锁定数据行进行更新，注意&#8220;for&nbsp;update&#8221;语句 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;st.executeQuery(</span><span class="string">"select&nbsp;BLOBATTR&nbsp;from&nbsp;TESTBLOB&nbsp;where&nbsp;ID=1&nbsp;for&nbsp;update"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(rs.next()) &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//得到java.sql.Blob对象后强制转换为oracle.sql.BLOB </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oracle.sql.BLOB&nbsp;blob&nbsp;=&nbsp;(oracle.sql.BLOB)&nbsp;rs.getBlob(</span><span class="string">"BLOBATTR"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;outStream&nbsp;=&nbsp;blob.getBinaryOutputStream(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//data是传入的byte数组，定义：byte[]&nbsp;data </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outStream.write(data,&nbsp;</span><span class="number">0</span><span>,&nbsp;data.length); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;outStream.flush(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;outStream.close(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;con.close();</span></font></font></li>
</ol>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<img src ="http://www.blogjava.net/jlin/aggbug/328130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-08-06 14:20 <a href="http://www.blogjava.net/jlin/articles/328130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdbc事务处理机制(转)</title><link>http://www.blogjava.net/jlin/articles/323881.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Sat, 19 Jun 2010 13:07:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/323881.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/323881.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/323881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/323881.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/323881.html</trackback:ping><description><![CDATA[<div class="blog_content">　　事务处理 <br />
<br />
　　信息是任何企事业单位的重要资产，任何企业部门都包含着信息的流入、流出，任何企业部门都控制着某些信息。同时，信息必须在适当的时机传播给需要的人。而且，信息还需要安全约束，通常根据信息的类型和内容实施访问控制。为了保证数据的安全有效和正确可靠，数据库管理系统（DBMS）必须提供统一的数据保护功能。 <br />
<br />
　　事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行，我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行，我们称该事务被提交。由于其中的一部分或多步执行失败，导致没有步骤被提交，则事务必须回滚（回到最初的系统状态）。事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性（atomicity）、一致性（consistency）、隔离性（isolation）和持久性（durability）的缩写。事务的原子性表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。一致性表示当事务执行失败时，所有被该事务影响的数据都应该恢复到事务执行前的状态。隔离性表示在事务执行过程中对数据的修改，在事务提交之前对其他事务不可见。持久性表示已提交的数据在事务执行失败时，数据的状态都应该正确。 <br />
<br />
　　在下面我们列举一个使用SQL Server数据库进行事务处理的例子。主表是一个规章制度信息表（bylaw），主要字段有记录编号、标题、作者、书写日期等。两个子表分别是附件表（bylaw_affix）和文本信息表（bylaw_content）。表结构见图1所示。bylaw表的记录编号与bylaw_affix表的记录编号、bylaw_content表的记录编号是对应的，每次对规章制度信息的操作也就是对这三个表的联合操作。例如要删除规章制度中的一条记录，如果不使用事务，就可能会出现这样的情况：第一个表中成功删除后，数据库突然出现意外状况，而第二、三个表中的操作没有完成，这样，删除操作并没有完成，甚至已经破坏数据库中的数据。要避免这种情况，就应该使用事务，它的作用是：要么三个表都操作成功，要么都失败。换句话说，就是保持数据的一致性。所以，为了确保对数据操作的完整和一致，在程序设计时要充分考虑到事务处理方面的问题。 <br />
<br />
<br />
图1 示例表结构 <br />
<br />
　　Java中的事务处理 <br />
<br />
　　一般情况下，J2EE应用服务器支持JDBC事务、JTA（Java Transaction API）事务、容器管理事务。一般情况下，最好不要在程序中同时使用上述三种事务类型，比如在JTA事务中嵌套JDBC事务。第二方面，事务要在尽可能短的时间内完成，不要在不同方法中实现事务的使用。下面我们列举两种事务处理方式。 <br />
<br />
　　1、JavaBean中使用JDBC方式进行事务处理 <br />
<br />
　　在JDBC中怎样将多个SQL语句组合成一个事务呢？在JDBC中，打开一个连接对象Connection时，缺省是auto-commit模式，每个SQL语句都被当作一个事务，即每次执行一个语句，都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务，要将auto-commit模式屏蔽掉。在auto-commit模式屏蔽掉之后，如果不调用commit()方法，SQL语句不会得到事务确认。在最近一次commit()方法调用之后的所有SQL会在方法commit()调用时得到确认。 <br />
<br />
public int delete(int sID) { <br />
　dbc = new DataBaseConnection(); <br />
　Connection con = dbc.getConnection(); <br />
　try { <br />
　　con.setAutoCommit(false);// 更改JDBC事务的默认提交方式 <br />
　　dbc.executeUpdate("delete from bylaw where ID=" + sID); <br />
　　dbc.executeUpdate("delete from bylaw _content where ID=" + sID); <br />
　　dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID); <br />
　　con.commit();//提交JDBC事务 <br />
　　con.setAutoCommit(true);// 恢复JDBC事务的默认提交方式 <br />
　　dbc.close(); <br />
　　return 1; <br />
　} <br />
　catch (Exception exc) { <br />
　　con.rollBack();//回滚JDBC事务 <br />
　　exc.printStackTrace(); <br />
　　dbc.close(); <br />
　　return -1; <br />
　} <br />
} <br />
<br />
　　2、SessionBean中的JTA事务 <br />
<br />
　　JTA 是事务服务的 J2EE 解决方案。本质上，它是描述事务接口（比如 UserTransaction 接口，开发人员直接使用该接口或者通过 J2EE 容器使用该接口来确保业务逻辑能够可靠地运行）的 J2EE 模型的一部分。JTA 具有的三个主要的接口分别是 UserTransaction 接口、TransactionManager 接口和 Transaction 接口。这些接口共享公共的事务操作，例如 commit() 和 rollback()， 但是也包含特殊的事务操作，例如 suspend()，resume() 和 enlist()，它们只出现在特定的接口上，以便在实现中允许一定程度的访问控制。例如，UserTransaction 能够执行事务划分和基本的事务操作，而 TransactionManager 能够执行上下文管理。 <br />
<br />
　　应用程序可以调用UserTransaction.begin()方法开始一个事务，该事务与应用程序正在其中运行的当前线程相关联。底层的事务管理器实际处理线程与事务之间的关联。UserTransaction.commit()方法终止与当前线程关联的事务。UserTransaction.rollback()方法将放弃与当前线程关联的当前事务。 <br />
<br />
public int delete(int sID) { <br />
　DataBaseConnection dbc = null; <br />
　dbc = new DataBaseConnection(); <br />
　dbc.getConnection(); <br />
　UserTransaction transaction = sessionContext.getUserTransaction();//获得JTA事务 <br />
　try { <br />
　　transaction.begin(); //开始JTA事务 <br />
　　dbc.executeUpdate("delete from bylaw where ID=" + sID); <br />
　　dbc.executeUpdate("delete from bylaw _content where ID=" + sID); <br />
　　dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID); <br />
　　transaction.commit(); //提交JTA事务 <br />
　　dbc.close(); <br />
　　return 1; <br />
　} <br />
　catch (Exception exc) { <br />
　　try { <br />
　　　transaction.rollback();//JTA事务回滚 <br />
　　} <br />
　　catch (Exception ex) { <br />
　　　//JTA事务回滚出错处理 <br />
　　　ex.printStackTrace(); <br />
　　} <br />
　　exc.printStackTrace(); <br />
　　dbc.close(); <br />
　　return -1; <br />
　} <br />
} <br />
加上的一些心得<br />
1.在数据库中，开启了事物，如果事物在提交之前发生了错误，如果系统回滚了，相应的数据不会提交。<br />
2.如果在事物提交了后发生了异常，即使在catch块中捕获了异常，系统也回滚不了。<br />
3.系统在回滚后，其以后的代码可以继续执行。<br />
</div>
<script type="text/javascript"><!-- google_ad_client="pub-1076724771190722" ;
/* JE个人博客468x60 */ google_ad_slot="5506163105" ; google_ad_width="468;
google_ad_height" = 60;
//-->
</script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script><script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script><script src="http://pagead2.googlesyndication.com/pagead/render_ads.js"></script><script>google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);</script>
<img src ="http://www.blogjava.net/jlin/aggbug/323881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-06-19 21:07 <a href="http://www.blogjava.net/jlin/articles/323881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle SQL性能优化(转)</title><link>http://www.blogjava.net/jlin/articles/322785.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Fri, 04 Jun 2010 10:00:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/322785.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/322785.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/322785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/322785.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/322785.html</trackback:ping><description><![CDATA[<p>oracle SQL性能优化 收藏 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习、摘录、并汇总部分资料与大家分享！ <br />
（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选择最有效率的表名顺序(只在基于规则的优化器中有效)：<br />
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名，FROM子句中写在最后的表(基础表 driving table)将被最先处理，在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.<br />
（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE子句中的连接顺序．：<br />
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.<br />
（3）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT子句中避免使用 &#8216; * &#8216;：<br />
ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间<br />
（4）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 减少访问数据库的次数：<br />
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等；<br />
（5）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200<br />
（6）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用DECODE函数来减少处理时间：<br />
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.<br />
（7）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 整合简单,无关联的数据库访问：<br />
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)<br />
（8）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 删除重复记录：<br />
最高效的删除重复记录方法 ( 因为使用了ROWID)例子：<br />
DELETE&nbsp; FROM&nbsp; EMP E&nbsp; WHERE&nbsp; E.ROWID &gt; (SELECT MIN(X.ROWID) <br />
FROM&nbsp; EMP X&nbsp; WHERE&nbsp; X.EMP_NO = E.EMP_NO);<br />
（9）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用TRUNCATE替代DELETE：<br />
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)<br />
（10） 尽量多使用COMMIT：<br />
只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: <br />
COMMIT所释放的资源: <br />
a. 回滚段上用于恢复数据的信息. <br />
b. 被程序语句获得的锁 <br />
c. redo log buffer 中的空间 <br />
d. ORACLE为管理上述3种资源中的内部花费<br />
（11） 用Where子句替换HAVING子句：<br />
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中，on是最先执行，where次之，having最后，因为on是先把不符合条件的记录过滤后才进行统计，它就可以减少中间运算要处理的数据，按理说应该速度是最快的，where也应该比having快点的，因为它过滤数据后才进行sum，在两个表联接时才用on的，所以在一个表的时候，就剩下where跟having比较了。在这单表查询统计的情况下，如果要过滤的条件没有涉及到要计算字段，那它们的结果是一样的，只是where可以使用rushmore技术，而having就不能，在速度上后者要慢如果要涉及到计算的字段，就表示在没计算之前，这个字段的值是不确定的，根据上篇写的工作流程，where的作用时间是在计算之前就完成的，而having就是在计算后才起作用的，所以在这种情况下，两者的结果会不同。在多表联接查询时，on比where更早起作用。系统首先根据各个表之间的联接条件，把多个表合成一个临时表后，再由where进行过滤，然后再计算，计算完后再由having进行过滤。由此可见，要想过滤条件起到正确的作用，首先要明白这个条件应该在什么时候起作用，然后再决定放在那里<br />
（12） 减少对表的查询：<br />
在含有子查询的SQL语句中,要特别注意减少对表的查询.例子：<br />
&nbsp;&nbsp;&nbsp;&nbsp; SELECT&nbsp; TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT<br />
TAB_NAME,DB_VER FROM&nbsp; TAB_COLUMNS&nbsp; WHERE&nbsp; VERSION = 604)<br />
（13） 通过内部函数提高SQL效率.：<br />
复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的<br />
（14） 使用表的别名(Alias)：<br />
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.<br />
（15） 用EXISTS替代IN、用NOT EXISTS替代NOT IN：<br />
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.<br />
例子：<br />
（高效）SELECT * FROM&nbsp; EMP (基础表)&nbsp; WHERE&nbsp; EMPNO &gt; 0&nbsp; AND&nbsp; EXISTS (SELECT &#8216;X'&nbsp; FROM DEPT&nbsp; WHERE&nbsp; DEPT.DEPTNO = EMP.DEPTNO&nbsp; AND&nbsp; LOC = &#8216;MELB')<br />
(低效)SELECT&nbsp; * FROM&nbsp; EMP (基础表)&nbsp; WHERE&nbsp; EMPNO &gt; 0&nbsp; AND&nbsp; DEPTNO IN(SELECT DEPTNO&nbsp; FROM&nbsp; DEPT&nbsp; WHERE&nbsp; LOC = &#8216;MELB')<br />
（16） 识别'低效执行'的SQL语句：<br />
虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法：<br />
SELECT&nbsp; EXECUTIONS , DISK_READS, BUFFER_GETS, <br />
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, <br />
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, <br />
SQL_TEXT <br />
FROM&nbsp; V$SQLAREA <br />
WHERE&nbsp; EXECUTIONS&gt;0 <br />
AND&nbsp; BUFFER_GETS &gt; 0 <br />
AND&nbsp; (BUFFER_GETS-DISK_READS)/BUFFER_GETS &lt; 0.8 <br />
ORDER BY&nbsp; 4 DESC;<br />
（17） 用索引提高效率：<br />
索引是表的一个概念部分,用来提高检索数据的效率，ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率. 虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引是有必要的.：<br />
ALTER&nbsp; INDEX &lt;INDEXNAME&gt; REBUILD &lt;TABLESPACENAME&gt;<br />
（18） 用EXISTS替换DISTINCT：<br />
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 例子：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (低效): <br />
SELECT&nbsp; DISTINCT&nbsp; DEPT_NO,DEPT_NAME&nbsp; FROM&nbsp; DEPT D , EMP E <br />
WHERE&nbsp; D.DEPT_NO = E.DEPT_NO <br />
(高效): <br />
SELECT&nbsp; DEPT_NO,DEPT_NAME&nbsp; FROM&nbsp; DEPT D&nbsp; WHERE&nbsp; EXISTS ( SELECT &#8216;X' <br />
FROM&nbsp; EMP E&nbsp; WHERE E.DEPT_NO = D.DEPT_NO);<br />
（19） sql语句用大写的；因为oracle总是先解析sql语句，把小写的字母转换成大写的再执行<br />
（20） 在java代码中尽量少用连接符&#8220;＋&#8221;连接字符串！<br />
（21） 避免在索引列上使用NOT 通常，　<br />
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE&#8221;遇到&#8221;NOT,他就会停止使用索引转而执行全表扫描.<br />
（22） 避免在索引列上使用计算．<br />
WHERE子句中，如果索引列是函数的一部分．优化器将不使用索引而使用全表扫描． <br />
举例: <br />
低效： <br />
SELECT &#8230; FROM&nbsp; DEPT&nbsp; WHERE SAL * 12 &gt; 25000; <br />
高效: <br />
SELECT &#8230; FROM DEPT WHERE SAL &gt; 25000/12;<br />
（23） 用&gt;=替代&gt;<br />
高效: <br />
SELECT * FROM&nbsp; EMP&nbsp; WHERE&nbsp; DEPTNO &gt;=4 <br />
低效: <br />
SELECT * FROM EMP WHERE DEPTNO &gt;3 <br />
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.<br />
（24） 用UNION替换OR (适用于索引列)<br />
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. <br />
高效: <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE LOC_ID = 10 <br />
UNION <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE REGION = &#8220;MELBOURNE&#8221; <br />
低效: <br />
SELECT LOC_ID , LOC_DESC , REGION <br />
FROM LOCATION <br />
WHERE LOC_ID = 10 OR REGION = &#8220;MELBOURNE&#8221; <br />
如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面.<br />
（25） 用IN来替换OR&nbsp; <br />
这是一条简单易记的规则，但是实际的执行效果还须检验，在ORACLE8i下，两者的执行路径似乎是相同的．　<br />
低效: <br />
SELECT&#8230;. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30 <br />
高效 <br />
SELECT&#8230; FROM LOCATION WHERE LOC_IN&nbsp; IN (10,20,30);<br />
（26） 避免在索引列上使用IS NULL和IS NOT NULL<br />
避免在索引中使用任何可以为空的列，ORACLE将无法使用该索引．对于单列索引，如果列包含空值，索引中将不存在此记录. 对于复合索引，如果每个列都为空，索引中同样不存在此记录.　如果至少有一个列不为空，则记录存在于索引中．举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值（123,null）的记录(插入). 然而如果所有的索引列都为空，ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.<br />
低效: (索引失效) <br />
SELECT &#8230; FROM&nbsp; DEPARTMENT&nbsp; WHERE&nbsp; DEPT_CODE IS NOT NULL; <br />
高效: (索引有效) <br />
SELECT &#8230; FROM&nbsp; DEPARTMENT&nbsp; WHERE&nbsp; DEPT_CODE &gt;=0;<br />
（27） 总是使用索引的第一个列：<br />
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则，当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引<br />
（28） 用UNION-ALL 替换UNION ( 如果有可能的话)：<br />
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是，UNION ALL 将重复输出两个结果集合中相同记录. 因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量<br />
低效： <br />
SELECT&nbsp; ACCT_NUM, BALANCE_AMT <br />
FROM&nbsp; DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
UNION <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
高效: <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95' <br />
UNION ALL <br />
SELECT ACCT_NUM, BALANCE_AMT <br />
FROM DEBIT_TRANSACTIONS <br />
WHERE TRAN_DATE = '31-DEC-95'<br />
（29） 用WHERE替代ORDER BY：<br />
ORDER BY 子句只在两种严格的条件下使用索引. <br />
ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. <br />
ORDER BY中所有的列必须定义为非空. <br />
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.<br />
例如: <br />
表DEPT包含以下列: <br />
DEPT_CODE PK NOT NULL <br />
DEPT_DESC NOT NULL <br />
DEPT_TYPE NULL<br />
低效: (索引不被使用) <br />
SELECT DEPT_CODE FROM&nbsp; DEPT&nbsp; ORDER BY&nbsp; DEPT_TYPE <br />
高效: (使用索引) <br />
SELECT DEPT_CODE&nbsp; FROM&nbsp; DEPT&nbsp; WHERE&nbsp; DEPT_TYPE &gt; 0<br />
（30） 避免改变索引列的类型.:<br />
当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. <br />
假设 EMPNO是一个数值类型的索引列. <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE&nbsp; EMPNO = &#8216;123' <br />
实际上,经过ORACLE类型转换, 语句转化为: <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE&nbsp; EMPNO = TO_NUMBER(&#8216;123') <br />
幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. <br />
现在,假设EMP_TYPE是一个字符类型的索引列. <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERE EMP_TYPE = 123 <br />
这个语句被ORACLE转换为: <br />
SELECT &#8230;&nbsp; FROM EMP&nbsp; WHERETO_NUMBER(EMP_TYPE)=123 <br />
因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型<br />
（31） 需要当心的WHERE子句:<br />
某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. <br />
在下面的例子里, (1)&#8216;!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) &#8216;||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) &#8216;+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.<br />
（32） a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高. <br />
b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!<br />
（33） 避免使用耗费资源的操作:<br />
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 <br />
执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强<br />
（34） 优化GROUP BY:<br />
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多.<br />
低效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP <br />
GROUP JOB <br />
HAVING JOB = &#8216;PRESIDENT' <br />
OR JOB = &#8216;MANAGER' <br />
高效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP <br />
WHERE JOB = &#8216;PRESIDENT' <br />
OR JOB = &#8216;MANAGER' <br />
GROUP JOB</p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/fuwei2241/archive/2006/09/06/1185198.aspx</p>
<img src ="http://www.blogjava.net/jlin/aggbug/322785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-06-04 18:00 <a href="http://www.blogjava.net/jlin/articles/322785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle procedure问题的解决(原)</title><link>http://www.blogjava.net/jlin/articles/321376.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Wed, 19 May 2010 06:54:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/321376.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/321376.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/321376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/321376.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/321376.html</trackback:ping><description><![CDATA[最近学习oracle存储过程时发现的一个问题，就是传入的变量命名不能跟要执行的数据表的字段一样，如果一样的话，<br />
可能会导致传入的参数起不了用处。例子如下： <br />
建立一个表:<br />
-- Create table<br />
create table T_TEST12<br />
(<br />
&nbsp; ID NUMBER,<br />
&nbsp; NO VARCHAR2(60)<br />
);<br />
往这个表里面插入一些数据，<br />
<p>insert into t_test12 (ID, NO)<br />
values (1, 'lin');</p>
<p>insert into t_test12 (ID, NO)<br />
values (2, '13800162');</p>
<p>insert into t_test12 (ID, NO)<br />
values (3, '13800163');</p>
<p>insert into t_test12 (ID, NO)<br />
values (4, '13800164');</p>
<p>insert into t_test12 (ID, NO)<br />
values (5, '13800165');</p>
<p>insert into t_test12 (ID, NO)<br />
values (6, '13800166');</p>
编写一个删除的存储过程，<br />
&nbsp;create or replace procedure delete_test(id in number) is&nbsp; --变量名称id跟数据库的字段一样<br />
begin<br />
&nbsp; delete from t_test12 where id =id;<br />
&nbsp; commit;<br />
end delete_test;<br />
执行以下操作：<br />
exec delete_test(1); 执行完后，发现并不是只删除了id为1的数据，<br />
而是把整个表的数据都删除了，如果要想得到相应的结果，则变量<br />
的命名不能跟表的字段名一样。比如如下：<br />
create or replace procedure delete_test(is_del_id in number) is&nbsp; --变量名称id跟数据库的字段一样<br />
begin<br />
&nbsp; delete from t_test12 where id =is_del_id;<br />
&nbsp; commit;<br />
end delete_test;<br />
<br />
<br />
<img src ="http://www.blogjava.net/jlin/aggbug/321376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-05-19 14:54 <a href="http://www.blogjava.net/jlin/articles/321376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.sql.SQLException: ORA-00911: invalid character 解决方法(转)</title><link>http://www.blogjava.net/jlin/articles/317591.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Tue, 06 Apr 2010 13:42:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/317591.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/317591.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/317591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/317591.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/317591.html</trackback:ping><description><![CDATA[<div class="tit">java.sql.SQLException: ORA-00911: invalid character</div>
<div class="date">2008年04月15日 星期二 10:37</div>
<table style="table-layout: fixed; width: 100%">
    <tbody>
        <tr>
            <td>
            <div class="cnt">
            <p>控制台抛出这个异常：java.sql.SQLException: ORA-00911: invalid character<br />
            查了一下说是oracle字符集设置的问题。我将抛异常的SQL语句在控制台输出如下：</p>
            <p>select count(t.id) as onerowc,t.id as areatravelid ,b.id as airpotid from base_areatravel t inner join base_airpot b on b.areaid=t.id group by t.id ,b.id;</p>
            <p>以上是完完整整的输出结果，然后我将语句复制到PL/SQL中执行是完全可以的，没有任何异常的。。</p>
            <p>而我在程序中定义的sql如下：</p>
            <p>String sql="select count(t.id) as onerowc,t.id as areatravelid ,b.id as airpotid from base_areatravel t"+<br />
            &nbsp;&nbsp;&nbsp; " inner join base_airpot b on b.areaid=t.id group by t.id ,b.id;";</p>
            <p>呵呵，花费了半个多小时终于找到原因：：：：</p>
            <p>哈哈，，定义语句中sql后面多了一个分号。（&#8220;；&#8221;）晕菜。。这样的话在PL/SQL中是无所谓的，可是Java 的数据库驱动却不识别这样的语句了。汗，，，太大意了。记录下来防止再次犯错，呵呵。。。</p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/jlin/aggbug/317591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-04-06 21:42 <a href="http://www.blogjava.net/jlin/articles/317591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle sql in中数据不能超过1000个的解决方法。</title><link>http://www.blogjava.net/jlin/articles/309076.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Mon, 11 Jan 2010 14:48:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/309076.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/309076.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/309076.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/309076.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/309076.html</trackback:ping><description><![CDATA[在Oracle中，sql中in不能超过1000个，比如：select&nbsp; * from table&nbsp; t where t.id in (1,2,3,......1001,1002)<br />
系统将报错，解决办法如下，写成两个或者多个。如：t.id in (1,2,....1000) or t.id in (1001,1002)<br />
实现代码如下：<br />
&nbsp;public String DivString(){<br />
&nbsp; StringBuffer sb = new StringBuffer();<br />
&nbsp; StringBuffer sb2 = new StringBuffer();<br />
&nbsp; List agentList = new ArrayList();<br />
&nbsp; for(int i =0;i&lt;1100;i++)&nbsp; <br />
&nbsp;&nbsp; agentList.add(i);<br />
&nbsp; for(int i=0;i&lt;agentList.size();i++){<br />
&nbsp;&nbsp; if(i==agentList.size()-1)<br />
&nbsp;&nbsp;&nbsp; sb.append("'").append(agentList.get(i)).append("')");<br />
&nbsp;&nbsp; else if(i%1000==0&amp;&amp;i&gt;0)<br />
&nbsp;&nbsp;&nbsp; sb.append("'").append(agentList.get(i)).append("'")<br />
&nbsp;&nbsp;&nbsp; .append(") or t.id in (");<br />
&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; sb.append("'").append(agentList.get(i)).append("',");<br />
&nbsp; }<br />
&nbsp; sb2.append(" t.id&nbsp; in ('',"+sb);<br />
&nbsp; System.out.println("sql is: "+sb2.toString());<br />
&nbsp; return sb2.toString();<br />
&nbsp;}
<img src ="http://www.blogjava.net/jlin/aggbug/309076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2010-01-11 22:48 <a href="http://www.blogjava.net/jlin/articles/309076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle用Start with...Connect By子句递归查询 (转)</title><link>http://www.blogjava.net/jlin/articles/300737.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Mon, 02 Nov 2009 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/300737.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/300737.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/300737.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/300737.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/300737.html</trackback:ping><description><![CDATA[<span id="ArticleContent1_ArticleContent1_lblContent">&nbsp;
<div>Start with...Connect By子句递归查询一般用于一个表维护树形结构的应用。</div>
<div>创建示例表：</div>
<div>CREATE TABLE TBL_TEST<br />
(<br />
&nbsp; ID&nbsp;&nbsp;&nbsp; NUMBER,<br />
&nbsp; NAME&nbsp; VARCHAR2(100 BYTE),<br />
&nbsp; PID&nbsp;&nbsp; NUMBER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DEFAULT 0<br />
);</div>
<div>&nbsp;</div>
<div>插入测试数据：</div>
<div>INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('1','10','0');<br />
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('2','11','1');<br />
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('3','20','0');<br />
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('4','12','1');<br />
INSERT INTO TBL_TEST(ID,NAME,PID) VALUES('5','121','2');</div>
<div>&nbsp;</div>
<div>从Root往树末梢递归</div>
<div>select * from TBL_TEST<br />
&nbsp;start with id=1<br />
&nbsp;connect by prior id = pid</div>
<div>&nbsp;</div>
<div>
<div>从末梢往树ROOT递归</div>
<div>select * from TBL_TEST<br />
&nbsp;start with id=5<br />
&nbsp;connect by prior pid = id</div>
</div>
</span><br />
<div style="font-size: 14px; line-height: 25px"><strong>作者Blog：</strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/54powerman/" target="_blank">http://blog.csdn.net/54powerman/</a></div>
<img src ="http://www.blogjava.net/jlin/aggbug/300737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2009-11-02 15:51 <a href="http://www.blogjava.net/jlin/articles/300737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle Oracle分页查询(转)</title><link>http://www.blogjava.net/jlin/articles/291681.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Tue, 18 Aug 2009 10:06:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/291681.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/291681.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/291681.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/291681.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/291681.html</trackback:ping><description><![CDATA[<p>Oracle分页查询</p>
<p>一.引用文章</p>
<p>SELECT&nbsp;/*+&nbsp;FIRST_ROWS&nbsp;*/&nbsp;*&nbsp;FROM&nbsp;<br />
(<br />
SELECT&nbsp;A.*,&nbsp;ROWNUM&nbsp;RN&nbsp;<br />
FROM&nbsp;(SELECT&nbsp;*&nbsp;FROM&nbsp;TABLE_NAME)&nbsp;A&nbsp;--不排序<br />
WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40<br />
)<br />
WHERE&nbsp;RN&nbsp;&gt;=&nbsp;21;</p>
<p>SELECT&nbsp;/*+&nbsp;FIRST_ROWS&nbsp;*/&nbsp;*<br />
FROM&nbsp;(SELECT&nbsp;a.*,&nbsp;row_number()&nbsp;over(ORDER&nbsp;BY&nbsp;1)&nbsp;rn--假排序，速度同上<br />
FROM&nbsp;t1&nbsp;a)<br />
WHERE&nbsp;rn&nbsp;BETWEEN&nbsp;21&nbsp;AND&nbsp;40;</p>
<p>SELECT&nbsp;*<br />
FROM&nbsp;(SELECT&nbsp;a.*,&nbsp;row_number()&nbsp;over(ORDER&nbsp;BY&nbsp;c1)&nbsp;rn&nbsp;--真实排序，无法比较速度<br />
FROM&nbsp;t1&nbsp;a)<br />
WHERE&nbsp;rn&nbsp;BETWEEN&nbsp;21&nbsp;AND&nbsp;40;</p>
<p>&nbsp;</p>
<p>Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用。<br />
分页查询格式：</p>
<p><br />
SELECT&nbsp;*&nbsp;FROM&nbsp;<br />
(<br />
SELECT&nbsp;A.*,&nbsp;ROWNUM&nbsp;RN&nbsp;<br />
FROM&nbsp;(SELECT&nbsp;*&nbsp;FROM&nbsp;TABLE_NAME)&nbsp;A&nbsp;<br />
WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40<br />
)<br />
WHERE&nbsp;RN&nbsp;&gt;=&nbsp;21</p>
<p>其中最内层的查询SELECT&nbsp;*&nbsp;FROM&nbsp;TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM&nbsp;&lt;=&nbsp;40和RN&nbsp;&gt;=&nbsp;21控制分页查询的每页的范围。</p>
<p>上面给出的这个分页查询语句，在大多数情况拥有较高的效率。分页的目的就是控制输出结果集大小，将结果尽快的返回。在上面的分页查询语句中，这种考虑主要体现在WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40这句上。</p>
<p>选择第21到40条记录存在两种方法，一种是上面例子中展示的在查询的第二层通过ROWNUM&nbsp;&lt;=&nbsp;40来控制最大值，在查询的最外层控制最小值。而另一种方式是去掉查询第二层的WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40语句，在查询的最外层控制分页的最小值和最大值。这是，查询语句如下：</p>
<p>SELECT&nbsp;*&nbsp;FROM&nbsp;<br />
(<br />
SELECT&nbsp;A.*,&nbsp;ROWNUM&nbsp;RN&nbsp;<br />
FROM&nbsp;(SELECT&nbsp;*&nbsp;FROM&nbsp;TABLE_NAME)&nbsp;A&nbsp;<br />
)<br />
WHERE&nbsp;RN&nbsp;BETWEEN&nbsp;21&nbsp;AND&nbsp;40</p>
<p>对比这两种写法，绝大多数的情况下，第一个查询的效率比第二个高得多。</p>
<p>这是由于CBO优化模式下，Oracle可以将外层的查询条件推到内层查询中，以提高内层查询的执行效率。对于第一个查询语句，第二层的查询条件WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40就可以被Oracle推入到内层查询中，这样Oracle查询的结果一旦超过了ROWNUM限制条件，就终止查询将结果返回了。</p>
<p>而第二个查询语句，由于查询条件BETWEEN&nbsp;21&nbsp;AND&nbsp;40是存在于查询的第三层，而Oracle无法将第三层的查询条件推到最内层（即使推到最内层也没有意义，因为最内层查询不知道RN代表什么）。因此，对于第二个查询语句，Oracle最内层返回给中间层的是所有满足条件的数据，而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成，显然这个效率要比第一个查询低得多。</p>
<p>上面分析的查询不仅仅是针对单表的简单查询，对于最内层查询是复杂的多表联合查询或最内层查询包含排序的情况一样有效。</p>
<p>这里就不对包含排序的查询进行说明了，下一篇文章会通过例子来详细说明。下面简单讨论一下多表联合的情况。对于最常见的等值表连接查询，CBO一般可能会采用两种连接方式NESTED&nbsp;LOOP和HASH&nbsp;JOIN（MERGE&nbsp;JOIN效率比HASH&nbsp;JOIN效率低，一般CBO不会考虑）。在这里，由于使用了分页，因此指定了一个返回的最大记录数，NESTED&nbsp;LOOP在返回记录数超过最大值时可以马上停止并将结果返回给中间层，而HASH&nbsp;JOIN必须处理完所有结果集（MERGE&nbsp;JOIN也是）。那么在大部分的情况下，对于分页查询选择NESTED&nbsp;LOOP作为查询的连接方法具有较高的效率（分页查询的时候绝大部分的情况是查询前几页的数据，越靠后面的页数访问几率越小）。</p>
<p>因此，如果不介意在系统中使用HINT的话，可以将分页的查询语句改写为：</p>
<p>SELECT&nbsp;/*+&nbsp;FIRST_ROWS&nbsp;*/&nbsp;*&nbsp;FROM&nbsp;<br />
(<br />
SELECT&nbsp;A.*,&nbsp;ROWNUM&nbsp;RN&nbsp;<br />
FROM&nbsp;(SELECT&nbsp;*&nbsp;FROM&nbsp;TABLE_NAME)&nbsp;A&nbsp;<br />
WHERE&nbsp;ROWNUM&nbsp;&lt;=&nbsp;40<br />
)<br />
WHERE&nbsp;RN&nbsp;&gt;=&nbsp;21</p>
<p>二.我的存储过程</p>
<p>create&nbsp;or&nbsp;replace&nbsp;package&nbsp;&nbsp;CJ_PageData&nbsp;is</p>
<p>TYPE&nbsp;type_cur&nbsp;IS&nbsp;REF&nbsp;CURSOR;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--建立游标</p>
<p>PROCEDURE&nbsp;CJ_GetDataByPage<br />
(<br />
tblName&nbsp;in&nbsp;&nbsp;varchar2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>strGetFields&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;</p>
<p>fldName&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>PageSize&nbsp;in&nbsp;&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>PageIndex&nbsp;in&nbsp;&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>doCount&nbsp;&nbsp;in&nbsp;number,&nbsp;&nbsp;&nbsp;</p>
<p>OrderType&nbsp;in&nbsp;number,&nbsp;&nbsp;</p>
<p>strWhere&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;</p>
<p>DataCount&nbsp;out&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>DataSet&nbsp;out&nbsp;type_cur&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>);<br />
end&nbsp;CJ_PageData;</p>
<p>CREATE&nbsp;OR&nbsp;REPLACE&nbsp;PACKAGE&nbsp;BODY&nbsp;CJ_PageData<br />
AS</p>
<p>PROCEDURE&nbsp;CJ_GetDataByPage<br />
(<br />
tblName&nbsp;in&nbsp;&nbsp;varchar2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--表名&nbsp;</p>
<p>strGetFields&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;--返回字段</p>
<p>fldName&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--排序字段名</p>
<p>PageSize&nbsp;in&nbsp;&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--分页大小&nbsp;&nbsp;</p>
<p>PageIndex&nbsp;in&nbsp;&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--页码&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>doCount&nbsp;&nbsp;in&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--是否统计(0否,1是)</p>
<p>OrderType&nbsp;in&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--排序类型(0降,1升)</p>
<p>strWhere&nbsp;in&nbsp;varchar2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--筛选条件</p>
<p>DataCount&nbsp;out&nbsp;number,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--返回记录总数&nbsp;&nbsp;&nbsp;</p>
<p>DataSet&nbsp;out&nbsp;type_cur&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--返回游标(指针)<br />
)</p>
<p>as</p>
<p>strSQL&nbsp;&nbsp;&nbsp;varchar2(5000)&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;临时记录Sql语句</p>
<p>strOrder&nbsp;varchar2(400)&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;临时记录排序语句</p>
<p>begin</p>
<p>if&nbsp;doCount&nbsp;&lt;&gt;&nbsp;0&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp;strWhere&nbsp;&lt;&gt;&nbsp;&nbsp;'&nbsp;'&nbsp;then<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSQL&nbsp;:=&nbsp;'select&nbsp;count(*)&nbsp;as&nbsp;total&nbsp;from&nbsp;'&nbsp;||&nbsp;tblName&nbsp;||&nbsp;'&nbsp;where&nbsp;'||strWhere;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSQL&nbsp;:=&nbsp;'select&nbsp;count(*)&nbsp;as&nbsp;total&nbsp;from&nbsp;'&nbsp;||&nbsp;tblName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;if;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execute&nbsp;immediate&nbsp;&nbsp;strSQL&nbsp;into&nbsp;DataCount;--取出记录总数放入返回变量DataCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end;</p>
<p>else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSQL&nbsp;:=&nbsp;'select&nbsp;'&nbsp;||strGetFields||'&nbsp;from&nbsp;(select&nbsp;T2.*,rownum&nbsp;rn&nbsp;from&nbsp;(select&nbsp;T1.*&nbsp;from&nbsp;'&nbsp;||&nbsp;tblName||'&nbsp;T1&nbsp;';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--得到排序类型语句<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;OrderType&nbsp;&lt;&gt;&nbsp;0&nbsp;then</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strOrder&nbsp;:=&nbsp;'&nbsp;order&nbsp;by&nbsp;'&nbsp;||&nbsp;fldName&nbsp;||'&nbsp;asc';&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strOrder&nbsp;:=&nbsp;'&nbsp;order&nbsp;by&nbsp;'&nbsp;||&nbsp;fldName&nbsp;||'&nbsp;desc';&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;if;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--组装SQl语句</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;strWhere&nbsp;&lt;&gt;&nbsp;'&nbsp;'&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSQL&nbsp;:=&nbsp;strSQL&nbsp;||&nbsp;'&nbsp;where&nbsp;'&nbsp;||&nbsp;strWhere&nbsp;||&nbsp;')&nbsp;T2&nbsp;where&nbsp;rownum&nbsp;&lt;='&nbsp;||&nbsp;TO_CHAR(PageIndex*PageSize)&nbsp;||&nbsp;')'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;'&nbsp;where&nbsp;rn&nbsp;&gt;'&nbsp;||&nbsp;TO_CHAR((PageIndex-1)*PageSize)&nbsp;||&nbsp;strOrder;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSQL&nbsp;:=&nbsp;strSQL&nbsp;||&nbsp;'&nbsp;)&nbsp;T2&nbsp;where&nbsp;rownum&nbsp;&lt;='&nbsp;||&nbsp;TO_CHAR(PageIndex*PageSize)&nbsp;||&nbsp;')'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;'&nbsp;where&nbsp;rn&nbsp;&gt;'&nbsp;||&nbsp;TO_CHAR((PageIndex-1)*PageSize)&nbsp;||&nbsp;strOrder;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;if;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end;<br />
end&nbsp;if;<br />
open&nbsp;DataSet&nbsp;for&nbsp;strSQL;<br />
end;</p>
<p>end&nbsp;CJ_PageData;</p>
<p>三,.Net中调用存储过程</p>
<p>1.方法</p>
<p>///&nbsp;&lt;summary&gt;<br />
&nbsp;&nbsp;///&nbsp;获得记录总数和所有记录{连接字符串,存储过程,表,返回字段,排序字段,分页大小,页码,统计(1是,0不是),排序(1升序,0降序),条件}<br />
&nbsp;&nbsp;///&nbsp;&lt;/summary&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strConn"&gt;&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strSPName"&gt;存储过程名字&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strTableName"&gt;表名&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strGetFields"&gt;返回字段字符串&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strFieldName"&gt;排序字段&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="iPageIndex"&gt;页码&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="iPageSize"&gt;分页大小&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="iDoCount"&gt;是否统计记录总数(1统计,0不统计)&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="iOrderType"&gt;排序类型(0升序,1降序)&lt;/param&gt;<br />
&nbsp;&nbsp;///&nbsp;&lt;param&nbsp;name="strWhere"&gt;筛选条件(不带where)&lt;/param&gt;<br />
&nbsp;&nbsp;protected&nbsp;void&nbsp;BuildData(string&nbsp;strConn,string&nbsp;strSPName,string&nbsp;strTableName,string&nbsp;strGetFields,string&nbsp;strFieldName,int&nbsp;iPageSize,int&nbsp;&nbsp;iPageIndex,int&nbsp;iDoCount,int&nbsp;iOrderType,string&nbsp;strWhere)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;System.Data.OracleClient.OracleConnection&nbsp;conn&nbsp;=&nbsp;new&nbsp;OracleConnection();<br />
&nbsp;&nbsp;&nbsp;System.Data.OracleClient.OracleCommand&nbsp;cmd&nbsp;=&nbsp;new&nbsp;OracleCommand();<br />
&nbsp;&nbsp;&nbsp;System.Data.OracleClient.OracleDataReader&nbsp;dr;</p>
<p>&nbsp;&nbsp;&nbsp;conn.ConnectionString&nbsp;=&nbsp;strConn;<br />
&nbsp;&nbsp;&nbsp;cmd.Connection&nbsp;=&nbsp;conn;<br />
&nbsp;&nbsp;&nbsp;cmd.CommandType&nbsp;=&nbsp;CommandType.StoredProcedure;</p>
<p>&nbsp;&nbsp;&nbsp;conn.Open();</p>
<p>&nbsp;&nbsp;&nbsp;cmd.CommandText&nbsp;=&nbsp;strSPName;</p>
<p>&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("tblName",OracleType.VarChar);//表名<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("strGetFields",OracleType.VarChar);//返回字段名<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("fldName",OracleType.VarChar);//排序字段名<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("PageSize",OracleType.Number);//分页大小<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("PageIndex",OracleType.Number);//页码<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("doCount",OracleType.Number);//是否统计总记录数<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("OrderType",OracleType.Number);//排序类型<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("strWhere",OracleType.VarChar);//筛选条件<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("DataCount",OracleType.Number);//返回得记录总数<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters.Add("DataSet",OracleType.Cursor);//返回得记录集</p>
<p><br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["tblName"].Value&nbsp;=&nbsp;strTableName;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["strGetFields"].Value&nbsp;=&nbsp;strGetFields;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["fldName"].Value&nbsp;=&nbsp;strFieldName;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["PageSize"].Value&nbsp;=&nbsp;iPageSize;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["PageIndex"].Value&nbsp;=&nbsp;(&nbsp;iOrderType&nbsp;==&nbsp;0&nbsp;)&nbsp;?&nbsp;(pager.PageCount+1-iPageIndex)&nbsp;:&nbsp;iPageIndex;//因为Oracle中不支持子查询排序,所以在这里如果需要倒序,则将页码按反序取数据,"以假乱真".嘿嘿!<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["doCount"].Value&nbsp;=&nbsp;iDoCount;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["OrderType"].Value&nbsp;=&nbsp;iOrderType;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["strWhere"].Value&nbsp;=&nbsp;strWhere;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["DataCount"].Direction&nbsp;=&nbsp;ParameterDirection.Output;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["DataSet"].Direction&nbsp;=&nbsp;ParameterDirection.Output;</p>
<p>&nbsp;&nbsp;&nbsp;cmd.Parameters["tblName"].Size&nbsp;=&nbsp;100;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["strGetFields"].Size&nbsp;=&nbsp;1000;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["fldName"].Size&nbsp;=&nbsp;100;<br />
&nbsp;&nbsp;&nbsp;cmd.Parameters["strWhere"].Size&nbsp;=&nbsp;1000;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;//try<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(iDoCount)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;0:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr&nbsp;=&nbsp;cmd.ExecuteReader();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dgData.DataSource&nbsp;=&nbsp;dr;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dgData.DataBind();//绑定数据源<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dr.Close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;1:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.ExecuteOracleScalar();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pager.RecordCount&nbsp;=&nbsp;int.Parse(cmd.Parameters["DataCount"].Value.ToString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;//catch<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;conn.Close();<br />
&nbsp;<br />
&nbsp;&nbsp;}</p>
<p>2.调用</p>
<p>A.页面加载时候取得总记录数,以绑定分页控件</p>
<p>private&nbsp;void&nbsp;Page_Load(object&nbsp;src,EventArgs&nbsp;e)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;if(!Page.IsPostBack)<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;conn&nbsp;=&nbsp;"password=cqcj;user&nbsp;id=cqcj;data&nbsp;source=cqc1";<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.BuildData(conn,"CJ_PageData.CJ_GetDataByPage","CJ_Log","","",0,0,1,0,"UserID&nbsp;=&nbsp;'xxr'");<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;BindData();//这里给分页控件.如DataGrid绑定数据源<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}</p>
<p>B.BindData()</p>
<p>protected&nbsp;void&nbsp;BindData()<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;string&nbsp;conn&nbsp;=&nbsp;"password=cqcj;user&nbsp;id=cqcj;data&nbsp;source=cqc1";</p>
<p>&nbsp;&nbsp;&nbsp;this.BuildData(conn,"CJ_PageData.CJ_GetDataByPage","CJ_Log","*","LoginTime",pager.PageSize,pager.CurrentPageIndex,0,1,"UserID&nbsp;=&nbsp;'xxr'");</p>
<p>&nbsp;&nbsp;&nbsp;pager.CustomInfoText="记录总数：&lt;font&nbsp;color=\"blue\"&gt;&lt;b&gt;"+pager.RecordCount.ToString()+"&lt;/b&gt;&lt;/font&gt;";<br />
&nbsp;&nbsp;&nbsp;pager.CustomInfoText+="&nbsp;总页数：&lt;font&nbsp;color=\"blue\"&gt;&lt;b&gt;"+pager.PageCount.ToString()+"&lt;/b&gt;&lt;/font&gt;";<br />
&nbsp;&nbsp;&nbsp;pager.CustomInfoText+="&nbsp;当前页：&lt;font&nbsp;color=\"red\"&gt;&lt;b&gt;"+pager.CurrentPageIndex.ToString()+"&lt;/b&gt;&lt;/font&gt;";<br />
&nbsp;&nbsp;}</p>
<p>四.总结</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Oracle中无法直接返回记录集,需利用游标返回.Oracle中不支持子查询排序.临时表耗费资源不推荐使用.<br />
</p>
<img src ="http://www.blogjava.net/jlin/aggbug/291681.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2009-08-18 18:06 <a href="http://www.blogjava.net/jlin/articles/291681.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>融会贯通Oracle数据库的25条基本知识(转)</title><link>http://www.blogjava.net/jlin/articles/288107.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Thu, 23 Jul 2009 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/288107.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/288107.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/288107.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/288107.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/288107.html</trackback:ping><description><![CDATA[1.一个表空间只能属于一个数据库。 <br />
<br />
<br />
2.每个数据库最少有一个控制文件（建议3个，分别放在不同的磁盘上）。 <br />
<br />
<br />
3.每个数据库最少有一个表空间（SYSTEM表空间）。 <br />
<br />
<br />
4.建立SYSTEM表空间的目的是尽量将目的相同的表存放在一起，以提高使用效率，只应存放数据字典。 <br />
<br />
<br />
5.每个数据库最少有两个联机日志组，每组最少一个联机日志文件。 <br />
<br />
<br />
6.一个数据文件只能属于一个表空间。 <br />
<br />
<br />
7.一个数据文件一旦被加入到一个表空间中，就不能再从这个表空间中移走，也不能再加入到其他表空间中。 <br />
<br />
<br />
8.建立新的表空间需要建立新的数据文件。 <br />
<br />
<br />
9.数据文件被ORACLE格式化为ORACLE块，Oracle9i以前版本中，ORACLE块的大小是在第一次创建数据库时设定的。 <br />
<br />
<br />
10.并且以后不能改变，要想改变，只能重建数据库。 <br />
<br />
<br />
11.一个段segment只能属于一个表空间，但可以属于多个数据文件。 <br />
<br />
<br />
12.一个区extent只能属于一个数据文件，即区间（extent）不能跨越数据文件。 <br />
<br />
<br />
13.PCTFREE和PCTUSED总和不能大于等于100。 <br />
<br />
<br />
14.单独一个事务不能跨越多个回滚段。 <br />
<br />
<br />
15.索引表不含ROWID值。 <br />
<br />
<br />
16.拥有不同大小的回滚段没有任何益处。 <br />
<br />
<br />
17.COMMIT后，数据不一定立即写盘（数据文件）。 <br />
<br />
<br />
18.一个事务即使不被提交，也会被写入到重做日志中。 <br />
<br />
<br />
19.Oracle 8.0.4中，在初始安装时建立的缺省数据库，实例名为ORCL 。 <br />
<br />
<br />
20.一个块的最大长度为16KB(有2K、4K、8K、16K)。 <br />
<br />
<br />
每个数据库最大文件数（按块大小） <br />
<br />
2K块　　　　　　　　20000个文件 <br />
<br />
4K块　　　　　　　　40000个文件 <br />
<br />
8K块或以上　　　　　65536个文件<br />
<br />
<br />
21.oracle server可以同时启动多个数据库 。 <br />
<br />
<br />
22.一套操作系统上可以安装多个版本的ORACLE数据库系统（UNIX可以，NT不可以）。 <br />
<br />
<br />
23.一套ORACLE数据库系统中可以有多个ORACLE数据库及其相对应的实例 。 <br />
<br />
<br />
24.每个Oracle数据库拥有一个数据库实例（INSTANCE）（OPS除外）。 <br />
<br />
<br />
25.所以，一套操作系统上同时可以有多个Oracle数据库实例启动。 <br />
<img src ="http://www.blogjava.net/jlin/aggbug/288107.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2009-07-23 22:26 <a href="http://www.blogjava.net/jlin/articles/288107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库连接的区别??</title><link>http://www.blogjava.net/jlin/articles/262412.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Fri, 27 Mar 2009 06:15:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/262412.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/262412.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/262412.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/262412.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/262412.html</trackback:ping><description><![CDATA[使用关系代数合并数据<br />
1 关系代数<br />
合并数据集合的理论基础是关系代数，它是由E.F.Codd于1970年提出的。<br />
在关系代数的形式化语言中：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用表、或者数据集合表示关系或者实体。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用行表示元组。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用列表示属性。<br />
关系代数包含以下8个关系运算符<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选取――返回满足指定条件的行。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 投影――从数据集合中返回指定的列。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 笛卡尔积――是关系的乘法，它将分别来自两个数据集合中的行以所有可能的方式进行组合。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 并――关系的加法和减法，它可以在行的方向上合并两个表中的数据，就像把一个表垒在另一个表之上一样。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 交――返回两个数据集合所共有的行。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 差――返回只属于一个数据集合的行。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 连接――在水平方向上合并两个表，其方法是：将两个表中在共同数据项上相互匹配的那些行合并起来。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 除――返回两个数据集之间的精确匹配。<br />
此外，作为一种实现现代关系代数运算的方法，SQL还提供了：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 子查询――类似于连接，但更灵活；在外部查询中，方式可以使用表达式、列表或者数据集合的地方都可以使用子查询的结果。<br />
本章将主要讲述多种类型的连接、简单的和相关的子查询、几种类型的并、关系除以及其他的内容。<br />
2 使用连接<br />
2.1 连接类型<br />
在关系代数中，连接运算是由一个笛卡尔积运算和一个选取运算构成的。首先用笛卡尔积完成对两个数据集合的乘运算，然后对生成的结果集合进行选取运算，确保只把分别来自两个数据集合并且具有重叠部分的行合并在一起。连接的全部意义在于在水平方向上合并两个数据集合（通常是表），并产生一个新的结果集合，其方法是将一个数据源中的行于另一个数据源中和它匹配的行组合成一个新元组。<br />
SQL提供了多种类型的连接方式，它们之间的区别在于：从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。<br />
连接类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义<br />
内连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 只连接匹配的行<br />
左外连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包含左边表的全部行（不管右边的表中是否存在与它们匹配的行），以及右边表中全部匹配的行<br />
右外连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包含右边表的全部行（不管左边的表中是否存在与它们匹配的行），以及左边表中全部匹配的行<br />
全外连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包含左、右两个表的全部行，不管另外一边的表中是否存在与它们匹配的行。<br />
(H)(theta)连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用等值以外的条件来匹配左、右两个表中的行<br />
交叉连接&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 生成笛卡尔积－它不使用任何匹配或者选取条件，而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配<br />
在INFORMIX中连接表的查询<br />
如果FROM子句指定了多于一个表引用，则查询会连接来自多个表的行。连接条件指定各列之间（每个表至少一列）进行连接的关系。因为正在比较连接条件中的列，所以它们必须具有一致的数据类型。<br />
SELECT语句的FROM子句可以指定以下几种类型的连接<br />
FROM子句关键字&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相应的结果集<br />
CROSS JOIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 笛卡尔乘积（所有可能的行对）<br />
INNER JOIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 仅对满足连接条件的CROSS中的列<br />
LEFT OUTER JOIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个表满足条件的行，和另一个表的所有行<br />
RIGHT OUTER JOIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与LEFT相同，但两个表的角色互换<br />
FULL OUTER JOIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LEFT OUTER 和 RIGHT OUTER中所有行的超集<br />
<br />
其中的outer，如果不写则表示默认。<br />
2.2 内连接（Inner Join）<br />
内连接是最常见的一种连接，它页被称为普通连接，而E.FCodd最早称之为自然连接。<br />
下面是ANSI SQL－92标准<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
inner join t_teller t <br />
on i.inst_no = t.inst_no<br />
where i.inst_no = "5801"<br />
其中inner可以省略。<br />
等价于早期的连接语法<br />
select * <br />
from t_institution i, t_teller t <br />
where i.inst_no = t.inst_no<br />
and i.inst_no = "5801"<br />
<br />
2.3 外连接<br />
2.3.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 左外连接(Left Outer Jion)<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
left outer join t_teller t <br />
on i.inst_no = t.inst_no<br />
其中outer可以省略。<br />
2.3.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 右外连接(Rigt Outer Jion)<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
right outer join t_teller t <br />
on i.inst_no = t.inst_no<br />
2.3.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 全外连接(Full Outer)<br />
全外连接返回参与连接的两个数据集合中的全部数据，无论它们是否具有与之相匹配的行。在功能上，它等价于对这两个数据集合分别进行左外连接和右外连接，然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。<br />
在现实生活中，参照完整性约束可以减少对于全外连接的使用，一般情况下左外连接就足够了。在数据库中没有利用清晰、规范的约束来防范错误数据情况下，全外连接就变得非常有用了，你可以使用它来清理数据库中的数据。<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
full outer join t_teller t <br />
on i.inst_no = t.inst_no<br />
2.3.4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 外连接与条件配合使用<br />
当在内连接查询中加入条件是，无论是将它加入到join子句，还是加入到where子句，其效果是完全一样的，但对于外连接情况就不同了。当把条件加入到join子句时，SQL Server、Informix会返回外连接表的全部行，然后使用指定的条件返回第二个表的行。如果将条件放到where子句中，SQL Server将会首先进行连接操作，然后使用where子句对连接后的行进行筛选。下面的两个查询展示了条件放置位子对执行结果的影响：<br />
条件在join子句<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
left outer join t_teller t <br />
on i.inst_no = t.inst_no<br />
and i.inst_no = &#8220;5801&#8221;<br />
结果是：<br />
inst_no&nbsp;&nbsp;&nbsp;&nbsp; inst_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inst_no&nbsp;&nbsp;&nbsp;&nbsp; teller_no&nbsp;&nbsp; teller_name<br />
5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天河区&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tom<br />
5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天河区&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0002&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; david<br />
5802&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 越秀区<br />
5803&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 白云区<br />
条件在where子句<br />
select * <br />
from&nbsp;&nbsp; t_institution i <br />
left outer join t_teller t <br />
on i.inst_no = t.inst_no<br />
where i.inst_no = &#8220;5801&#8221;<br />
结果是：<br />
inst_no&nbsp;&nbsp;&nbsp;&nbsp; inst_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inst_no&nbsp;&nbsp;&nbsp;&nbsp; teller_no&nbsp;&nbsp; teller_name<br />
5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天河区&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tom<br />
5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天河区&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0002&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; david<br />
<br />
2.4 自身连接<br />
自身连接是指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系（也称作递归关系）中抽取数据。例如人力资源数据库中雇员与老板的关系。<br />
下面例子是在机构表中查找本机构和上级机构的信息。<br />
select s.inst_no superior_inst, s.inst_name sup_inst_name, i.inst_no, i.inst_name<br />
from t_institution i<br />
join t_institution s<br />
on i.superior_inst = s.inst_no<br />
<br />
结果是：<br />
superior_inst sup_inst_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inst_no&nbsp;&nbsp;&nbsp;&nbsp; inst_name<br />
800&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 广州市&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 天河区<br />
800&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 广州市&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5802&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 越秀区<br />
800&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 广州市&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5803&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 白云区<br />
<br />
2.5 交叉(无限制) 连接<br />
交叉连接用于对两个源表进行纯关系代数的乘运算。它不使用连接条件来限制结果集合，而是将分别来自两个数据源中的行以所有可能的方式进行组合。数据集合中一的每个行都要与数据集合二中的每一个行分别组成一个新的行。例如，如果第一个数据源中有5个行，而第二个数据源中有4个行，那么在它们之间进行交叉连接就会产生20个行。人们将这种类型的结果集称为笛卡尔乘积。<br />
大多数交叉连接都是由于错误操作而造成的；但是它们却非常适合向数据库中填充例子数据，或者预先创建一些空行以便为程序执行期间所要填充的数据保留空间。<br />
select *<br />
from&nbsp;&nbsp; t_institution i <br />
cross join t_teller t<br />
在交叉连接中没有on条件子句<br />
<br />
3 APPENDIX<br />
3.1 A 参考资料与资源<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 《Microsoft SQL Server 2000 Bile》Paul Nielsen<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Paul Nielsen的Web站点<br />
www.isnotnull.com<br />
3.2 注文章所有SQL在IBM Informix Dynamic Server Version 9.40.TC2E1测试通过&nbsp;&nbsp;<br />
<br />
<p>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=940779</p>
<img src ="http://www.blogjava.net/jlin/aggbug/262412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2009-03-27 14:15 <a href="http://www.blogjava.net/jlin/articles/262412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单讲述基于SQL SERVER 分页的存储过程(转)</title><link>http://www.blogjava.net/jlin/articles/231463.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Sat, 27 Sep 2008 03:52:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/231463.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/231463.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/231463.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/231463.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/231463.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 笔者打算通过本文也来简单谈一下基于SQL SERVER 2000的分页存储过程，同时谈谈SQL SERVER 2005下分页存储过程的演进。 在进行基于UI显示的数据分页时，常见的数据提取方式主要有两种。第一种是从数据库提取所有数据然后在系统应用程序层进行数据分页，显示当前页数据。第二种分页方式为从数据库取出需要显示的一页数据显示在UI界面上。以下是笔者对两种实现方式所做的优缺点比较，针对...&nbsp;&nbsp;<a href='http://www.blogjava.net/jlin/articles/231463.html'>阅读全文</a><img src ="http://www.blogjava.net/jlin/aggbug/231463.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2008-09-27 11:52 <a href="http://www.blogjava.net/jlin/articles/231463.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MS SQL 2000 存储过程</title><link>http://www.blogjava.net/jlin/articles/63054.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Fri, 11 Aug 2006 09:09:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/63054.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/63054.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/63054.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/63054.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/63054.html</trackback:ping><description><![CDATA[
		<p>------------------------------------------------------------------------------------------------------------------------------------------------------<br />自己写的存储过程：<br />use test<br />go</p>
		<p>if exists (select name from sysobjects where name='v_order' and type='p')<br />DROP PROCEDURE v_order<br />go</p>
		<p>create procedure v_order <br /> @serverid varchar(30),<br /> @jtype   int <br /> as <br /> select * from <br /> order_form<br />where jtype= @jtype and <a href="mailto:serverid=@serverid">serverid=@serverid</a></p>
		<p>select * from sysobjects where type='p' and name='v_order'</p>
		<p>exec v_order 'hcair','3'<br />go<br />exec v_order hcair,3</p>
		<p>exec v_order @serverid=hcair,@jtype=3</p>
		<p>
				<br />drop proc v_order_in<br />go<br />create procedure v_order_in<br />@user_name varchar(20),<br />@pnr_list  varchar(20),<br />@air_list  varchar(20),<br />@arri_list  varchar(20),<br />@dp_time    timestamp,<br />@lxname   varchar(20)<br />as <br />insert into order_form(user_name,pnr_list,air_list,arri_list,dp_time,lxname) values (@user_name,@pnr_list,@air_list,@arri_list,@dp_time,@lxname )<br />go</p>
		<p>exec v_order_in 0000,rksts,MF8587,'KHN,PEK,',convert('2006-7-16 13:03:53'),linsanfu<br />-------------------------------------------------------------------------------------------------------------------------------------------------------<br />示例<br />A. 使用带有复杂 SELECT 语句的简单过程<br />下面的存储过程从四个表的联接中返回所有作者（提供了姓名）、出版的书籍以及出版社。该存储过程不使用任何参数。</p>
		<p>USE pubs<br />IF EXISTS (SELECT name FROM sysobjects <br />         WHERE name = 'au_info_all' AND type = 'P')<br />   DROP PROCEDURE au_info_all<br />GO<br />CREATE PROCEDURE au_info_all<br />AS<br />SELECT au_lname, au_fname, title, pub_name<br />   FROM authors a INNER JOIN titleauthor ta<br />      ON a.au_id = ta.au_id INNER JOIN titles t<br />      ON t.title_id = ta.title_id INNER JOIN publishers p<br />      ON t.pub_id = p.pub_id<br />GO</p>
		<p>au_info_all 存储过程可以通过以下方法执行：</p>
		<p>EXECUTE au_info_all<br />-- Or<br />EXEC au_info_all</p>
		<p>如果该过程是批处理中的第一条语句，则可使用：</p>
		<p>au_info_all</p>
		<p>B. 使用带有参数的简单过程<br />下面的存储过程从四个表的联接中只返回指定的作者（提供了姓名）、出版的书籍以及出版社。该存储过程接受与传递的参数精确匹配的值。</p>
		<p>USE pubs<br />IF EXISTS (SELECT name FROM sysobjects <br />         WHERE name = 'au_info' AND type = 'P')<br />   DROP PROCEDURE au_info<br />GO<br />USE pubs<br />GO<br />CREATE PROCEDURE au_info <br />   @lastname varchar(40), <br />   @firstname varchar(20) <br />AS <br />SELECT au_lname, au_fname, title, pub_name<br />   FROM authors a INNER JOIN titleauthor ta<br />      ON a.au_id = ta.au_id INNER JOIN titles t<br />      ON t.title_id = ta.title_id INNER JOIN publishers p<br />      ON t.pub_id = p.pub_id<br />   WHERE  au_fname = @firstname<br />      AND au_lname = @lastname<br />GO</p>
		<p>au_info 存储过程可以通过以下方法执行：</p>
		<p>EXECUTE au_info 'Dull', 'Ann'<br />-- Or<br />EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann'<br />-- Or<br />EXECUTE au_info @firstname = 'Ann', @lastname = 'Dull'<br />-- Or<br />EXEC au_info 'Dull', 'Ann'<br />-- Or<br />EXEC au_info @lastname = 'Dull', @firstname = 'Ann'<br />-- Or<br />EXEC au_info @firstname = 'Ann', @lastname = 'Dull'</p>
		<p>如果该过程是批处理中的第一条语句，则可使用：</p>
		<p>au_info 'Dull', 'Ann'<br />-- Or<br />au_info @lastname = 'Dull', @firstname = 'Ann'<br />-- Or<br />au_info @firstname = 'Ann', @lastname = 'Dull'</p>
		<p>C. 使用带有通配符参数的简单过程<br />下面的存储过程从四个表的联接中只返回指定的作者（提供了姓名）、出版的书籍以及出版社。该存储过程对传递的参数进行模式匹配，如果没有提供参数，则使用预设的默认值。</p>
		<p>USE pubs<br />IF EXISTS (SELECT name FROM sysobjects <br />      WHERE name = 'au_info2' AND type = 'P')<br />   DROP PROCEDURE au_info2<br />GO<br />USE pubs<br />GO<br />CREATE PROCEDURE au_info2<br />   @lastname varchar(30) = 'D%',<br />   @firstname varchar(18) = '%'<br />AS <br />SELECT au_lname, au_fname, title, pub_name<br />FROM authors a INNER JOIN titleauthor ta<br />   ON a.au_id = ta.au_id INNER JOIN titles t<br />   ON t.title_id = ta.title_id INNER JOIN publishers p<br />   ON t.pub_id = p.pub_id<br />WHERE au_fname LIKE @firstname<br />   AND au_lname LIKE @lastname<br />GO</p>
		<p>au_info2 存储过程可以用多种组合执行。下面只列出了部分组合：</p>
		<p>EXECUTE au_info2<br />-- Or<br />EXECUTE au_info2 'Wh%'<br />-- Or<br />EXECUTE au_info2 @firstname = 'A%'<br />-- Or<br />EXECUTE au_info2 '[CK]ars[OE]n'<br />-- Or<br />EXECUTE au_info2 'Hunter', 'Sheryl'<br />-- Or<br />EXECUTE au_info2 'H%', 'S%'</p>
		<p>D. 使用 OUTPUT 参数<br />OUTPUT 参数允许外部过程、批处理或多条 Transact-SQL 语句访问在过程执行期间设置的某个值。下面的示例创建一个存储过程 (titles_sum)，并使用一个可选的输入参数和一个输出参数。</p>
		<p>首先，创建过程：</p>
		<p>USE pubs<br />GO<br />IF EXISTS(SELECT name FROM sysobjects<br />      WHERE name = 'titles_sum' AND type = 'P')<br />   DROP PROCEDURE titles_sum<br />GO<br />USE pubs<br />GO<br />CREATE PROCEDURE titles_sum @@TITLE varchar(40) = '%', @@SUM money OUTPUT<br />AS<br />SELECT 'Title Name' = title<br />FROM titles <br />WHERE title LIKE @@TITLE <br />SELECT @@SUM = SUM(price)<br />FROM titles<br />WHERE title LIKE @@TITLE<br />GO</p>
		<p>接下来，将该 OUTPUT 参数用于控制流语言。 </p>
		<p> </p>
		<p>说明  OUTPUT 变量必须在创建表和使用该变量时都进行定义。</p>
		<p>
				<br />参数名和变量名不一定要匹配，不过数据类型和参数位置必须匹配（除非使用 @@SUM = variable 形式）。 </p>
		<p>DECLARE @@TOTALCOST money<br />EXECUTE titles_sum 'The%', @@TOTALCOST OUTPUT<br />IF @@TOTALCOST &lt; 200 <br />BEGIN<br />   PRINT ' '<br />   PRINT 'All of these titles can be purchased for less than $200.'<br />END<br />ELSE<br />   SELECT 'The total cost of these titles is $' <br />         + RTRIM(CAST(@@TOTALCOST AS varchar(20)))</p>
		<p>下面是结果集：</p>
		<p>Title Name                                                               <br />------------------------------------------------------------------------ <br />The Busy Executive's Database Guide<br />The Gourmet Microwave<br />The Psychology of Computer Cooking</p>
		<p>(3 row(s) affected)</p>
		<p>Warning, null value eliminated from aggregate.<br /> <br />All of these titles can be purchased for less than $200.</p>
		<p>E. 使用 OUTPUT 游标参数<br />OUTPUT 游标参数用来将存储过程的局部游标传递回调用批处理、存储过程或触发器。</p>
		<p>首先，创建以下过程，在 titles 表上声明并打开一个游标：</p>
		<p>USE pubs<br />IF EXISTS (SELECT name FROM sysobjects <br />      WHERE name = 'titles_cursor' and type = 'P')<br />DROP PROCEDURE titles_cursor<br />GO<br />CREATE PROCEDURE titles_cursor @titles_cursor CURSOR VARYING OUTPUT<br />AS<br />SET @titles_cursor = CURSOR<br />FORWARD_ONLY STATIC FOR<br />SELECT *<br />FROM titles</p>
		<p>OPEN @titles_cursor<br />GO</p>
		<p>接下来，执行一个批处理，声明一个局部游标变量，执行上述过程以将游标赋值给局部变量，然后从该游标提取行。</p>
		<p>USE pubs<br />GO<br />DECLARE @MyCursor CURSOR<br />EXEC titles_cursor @titles_cursor = @MyCursor OUTPUT<br />WHILE (@@FETCH_STATUS = 0)<br />BEGIN<br />   FETCH NEXT FROM @MyCursor<br />END<br />CLOSE @MyCursor<br />DEALLOCATE @MyCursor<br />GO</p>
		<p>F. 使用 WITH RECOMPILE 选项<br />如果为过程提供的参数不是典型的参数，并且新的执行计划不应高速缓存或存储在内存中，WITH RECOMPILE 子句会很有帮助。</p>
		<p>USE pubs<br />IF EXISTS (SELECT name FROM sysobjects<br />      WHERE name = 'titles_by_author' AND type = 'P')<br />   DROP PROCEDURE titles_by_author<br />GO<br />CREATE PROCEDURE titles_by_author @@LNAME_PATTERN varchar(30) = '%'<br />WITH RECOMPILE<br />AS<br />SELECT RTRIM(au_fname) + ' ' + RTRIM(au_lname) AS 'Authors full name',<br />   title AS Title<br />FROM authors a INNER JOIN titleauthor ta <br />   ON a.au_id = ta.au_id INNER JOIN titles t<br />   ON ta.title_id = t.title_id<br />WHERE au_lname LIKE @@LNAME_PATTERN<br />GO</p>
		<p>G. 使用 WITH ENCRYPTION 选项<br />WITH ENCRYPTION 子句对用户隐藏存储过程的文本。下例创建加密过程，使用 sp_helptext 系统存储过程获取关于加密过程的信息，然后尝试直接从 syscomments 表中获取关于该过程的信息。</p>
		<p>IF EXISTS (SELECT name FROM sysobjects<br />      WHERE name = 'encrypt_this' AND type = 'P')<br />   DROP PROCEDURE encrypt_this<br />GO<br />USE pubs<br />GO<br />CREATE PROCEDURE encrypt_this<br />WITH ENCRYPTION<br />AS<br />SELECT * <br />FROM authors<br />GO</p>
		<p>EXEC sp_helptext encrypt_this</p>
		<p>下面是结果集：</p>
		<p>The object's comments have been encrypted.</p>
		<p>接下来，选择加密存储过程内容的标识号和文本。</p>
		<p>SELECT c.id, c.text <br />FROM syscomments c INNER JOIN sysobjects o<br />   ON c.id = o.id<br />WHERE o.name = 'encrypt_this'</p>
		<p>下面是结果集：</p>
		<p> </p>
		<p>说明  text 列的输出显示在单独一行中。执行时，该信息将与 id 列信息出现在同一行中。</p>
		<p>
				<br />id         text                                                        <br />---------- ------------------------------------------------------------<br />1413580074 ?????????????????????????????????e??????????????????????????????????????????????????????????????????????????</p>
		<p>(1 row(s) affected)</p>
		<p>H. 创建用户定义的系统存储过程<br />下面的示例创建一个过程，显示表名以 emp 开头的所有表及其对应的索引。如果没有指定参数，该过程将返回表名以 sys 开头的所有表（及索引）。</p>
		<p>IF EXISTS (SELECT name FROM sysobjects<br />      WHERE name = 'sp_showindexes' AND type = 'P')<br />   DROP PROCEDURE sp_showindexes<br />GO<br />USE master<br />GO<br />CREATE PROCEDURE sp_showindexes<br />   @@TABLE varchar(30) = 'sys%'<br />AS <br />SELECT o.name AS TABLE_NAME,<br />   i.name AS INDEX_NAME, <br />   indid AS INDEX_ID<br />FROM sysindexes i INNER JOIN sysobjects o<br />   ON o.id = i.id <br />WHERE o.name LIKE @@TABLE<br />GO         <br />USE pubs<br />EXEC sp_showindexes 'emp%'<br />GO</p>
		<p>下面是结果集：</p>
		<p>TABLE_NAME       INDEX_NAME       INDEX_ID <br />---------------- ---------------- ----------------<br />employee         employee_ind     1<br />employee         PK_emp_id        2</p>
		<p>(2 row(s) affected)</p>
		<p>I. 使用延迟名称解析<br />下面的示例显示四个过程以及延迟名称解析的各种可能使用方式。尽管引用的表或列在编译时不存在，但每个存储过程都可创建。</p>
		<p>IF EXISTS (SELECT name FROM sysobjects<br />      WHERE name = 'proc1' AND type = 'P')<br />   DROP PROCEDURE proc1<br />GO<br />-- Creating a procedure on a nonexistent table.<br />USE pubs<br />GO<br />CREATE PROCEDURE proc1<br />AS<br />   SELECT *<br />   FROM does_not_exist<br />GO  <br />-- Here is the statement to actually see the text of the procedure.<br />SELECT o.id, c.text<br />FROM sysobjects o INNER JOIN syscomments c <br />   ON o.id = c.id<br />WHERE o.type = 'P' AND o.name = 'proc1'<br />GO<br />USE master<br />GO<br />IF EXISTS (SELECT name FROM sysobjects<br />      WHERE name = 'proc2' AND type = 'P')<br />   DROP PROCEDURE proc2<br />GO<br />-- Creating a procedure that attempts to retrieve information from a<br />-- nonexistent column in an existing table.<br />USE pubs<br />GO<br />CREATE PROCEDURE proc2<br />AS<br />   DECLARE @middle_init char(1)<br />   SET @middle_init = NULL<br />   SELECT au_id, middle_initial = @middle_init<br />   FROM authors<br />GO  <br />-- Here is the statement to actually see the text of the procedure.<br />SELECT o.id, c.text<br />FROM sysobjects o INNER JOIN syscomments c <br />   ON o.id = c.id<br />WHERE o.type = 'P' and o.name = 'proc2'</p>
		<p> </p>
<img src ="http://www.blogjava.net/jlin/aggbug/63054.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2006-08-11 17:09 <a href="http://www.blogjava.net/jlin/articles/63054.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MSSQL数据类型</title><link>http://www.blogjava.net/jlin/articles/63051.html</link><dc:creator>fly</dc:creator><author>fly</author><pubDate>Fri, 11 Aug 2006 09:06:00 GMT</pubDate><guid>http://www.blogjava.net/jlin/articles/63051.html</guid><wfw:comment>http://www.blogjava.net/jlin/comments/63051.html</wfw:comment><comments>http://www.blogjava.net/jlin/articles/63051.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jlin/comments/commentRss/63051.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jlin/services/trackbacks/63051.html</trackback:ping><description><![CDATA[
		<p>4.3.1 整数数据类型 <br />    整数数据类型是最常用的数据类型之一。<br />     1、INT （INTEGER）<br />INT （或INTEGER）数据类型存储从-2的31次方 （-2 ，147 ，483 ，648） 到2的31次方-1 （2 ，147 ，483，647） 之间的所有正负整数。每个INT 类型的数据按4 个字节存储，其中1 位表示整数值的正负号，其它31 位表示整数值的长度和大小。 <br />     2、SMALLINT<br />SMALLINT 数据类型存储从-2的15次方（ -32， 768） 到2的15次方-1（ 32 ，767 ）之间的所有正负整数。每个SMALLINT 类型的数据占用2 个字节的存储空间，其中1 位表示整数值的正负号，其它15 位表示整数值的长度和大小。<br />     3、TINYINT<br />TINYINT数据类型存储从0 到255 之间的所有正整数。每个TINYINT类型的数据占用1 个字节的存储空间。<br />     4、BIGINT<br />BIGINT 数据类型存储从-2^63 （-9 ，223， 372， 036， 854， 775， 807） 到2^63-1（ 9， 223， 372， 036 ，854 ，775， 807） 之间的所有正负整数。每个BIGINT 类型的数据占用8个字节的存储空间。</p>
		<p>4.3.2 浮点数据类型<br />    浮点数据类型用于存储十进制小数。浮点数值的数据在SQL Server 中采用上舍入（Round up 或称为只入不舍）方式进行存储。所谓上舍入是指，当（且仅当）要舍入的数是一个非零数时，对其保留数字部分的最低有效位上的数值加1 ，并进行必要的进位。若一个数是上舍入数，其绝对值不会减少。如：对3.14159265358979 分别进行2 位和12位舍入，结果为3.15 和3.141592653590。<br />     1、REAL 数据类型<br />REAL数据类型可精确到第7 位小数，其范围为从-3.40E -38 到3.40E +38。 每个REAL类型的数据占用4 个字节的存储空间。<br />     2、FLOAT<br />FLOAT数据类型可精确到第15 位小数，其范围为从-1.79E -308 到1.79E +308。 每个FLOAT 类型的数据占用8 个字节的存储空间。 FLOAT数据类型可写为FLOAT[ n ]的形式。n 指定FLOAT 数据的精度。n 为1到15 之间的整数值。当n 取1 到7 时，实际上是定义了一个REAL 类型的数据，系统用4 个字节存储它；当n 取8 到15 时，系统认为其是FLOAT 类型，用8 个字节存储它。<br />     3、DECIMAL<br />DECIMAL数据类型可以提供小数所需要的实际存储空间，但也有一定的限制，您可以用2 到17 个字节来存储从-10的38次方-1 到10的38次方-1 之间的数值。可将其写为DECIMAL[ p [s] ]的形式，p 和s 确定了精确的比例和数位。其中p 表示可供存储的值的总位数（不包括小数点），缺省值为18； s 表示小数点后的位数，缺省值为0。 例如：decimal （15 5），表示共有15 位数，其中整数10 位，小数5。 位表4-3 列出了各精确度所需的字节数之间的关系。<br />  <br />     4、NUMERIC<br />NUMERIC数据类型与DECIMAL数据类型完全相同。<br />注意：SQL Server 为了和前端的开发工具配合，其所支持的数据精度默认最大为28位。但可以通过使用命令来执行sqlserver.exe程序以启动SQL Server，可改变默认精度。命令语法如下：SQLSERVR[/D master_device_path][/P precisim_leve1]<br />    例4-4: 用最大数据精度38 启动SQL Server<br />sqlservr /d c:\ Mssql2000\data\master.dat /p38<br />/*在使用了/P 参数后,如果其后没有指定具体的精度数值,则默认为38 位./* <br />4.3.3 二进制数据类型<br />     1、BINARY<br />BINARY 数据类型用于存储二进制数据。其定义形式为BINARY（ n）， n 表示数据的长度，取值为1 到8000 。在使用时必须指定BINARY 类型数据的大小，至少应为1 个字节。BINARY 类型数据占用n+4 个字节的存储空间。在输入数据时必须在数据前加上字符“0X” 作为二进制标识，如：要输入“abc ”则应输入“0xabc ”。若输入的数据过长将会截掉其超出部分。若输入的数据位数为奇数，则会在起始符号“0X ”后添加一个0，如上述的“0xabc ”会被系统自动变为“0x0abc”。 <br />     2、VARBINARY<br />VARBINARY数据类型的定义形式为VARBINARY（n）。 它与BINARY 类型相似，n 的取值也为1 到8000， 若输入的数据过长，将会截掉其超出部分。不同的是VARBINARY数据类型具有变动长度的特性，因为VARBINARY数据类型的存储长度为实际数值长度+4个字节。当BINARY数据类型允许NULL 值时，将被视为VARBINARY数据类型。<br />一般情况下，由于BINARY 数据类型长度固定，因此它比VARBINARY 类型的处理速度快。</p>
		<p>4.3.4 逻辑数据类型 <br />    BIT： BIT数据类型占用1 个字节的存储空间，其值为0 或1 。如果输入0 或1 以外的值，将被视为1。 BIT 类型不能定义为NULL 值（所谓NULL 值是指空值或无意义的值）。</p>
		<p>4.3.5 字符数据类型<br />    字符数据类型是使用最多的数据类型。它可以用来存储各种字母、数字符号、特殊符号。一般情况下，使用字符类型数据时须在其前后加上单引号’或双引号” 。 <br />     1 CHAR<br />CHAR 数据类型的定义形式为CHAR[ （n） ]。 以CHAR 类型存储的每个字符和符号占一个字节的存储空间。n 表示所有字符所占的存储空间，n 的取值为1 到8000， 即可容纳8000 个ANSI 字符。若不指定n 值，则系统默认值为1。 若输入数据的字符数小于n，则系统自动在其后添加空格来填满设定好的空间。若输入的数据过长，将会截掉其超出部分。<br />     2、NCHAR<br />NCHAR数据类型的定义形式为NCHAR[ （n） ]。 它与CHAR 类型相似。不同的是NCHAR数据类型n 的取值为1 到4000。 因为NCHAR 类型采用UNICODE 标准字符集（CharacterSet）。 UNICODE 标准规定每个字符占用两个字节的存储空间，所以它比非UNICODE 标准的数据类型多占用一倍的存储空间。使用UNICODE 标准的好处是因其使用两个字节做存储单位，其一个存储单位的容纳量就大大增加了，可以将全世界的语言文字都囊括在内，在一个数据列中就可以同时出现中文、英文、法文、德文等，而不会出现编码冲突。<br />     3、VARCHAR<br />VARCHAR数据类型的定义形式为VARCHAR [ （n） ]。 它与CHAR 类型相似，n 的取值也为1 到8000， 若输入的数据过长，将会截掉其超出部分。不同的是，VARCHAR数据类型具有变动长度的特性，因为VARCHAR数据类型的存储长度为实际数值长度，若输入数据的字符数小于n ，则系统不会在其后添加空格来填满设定好的空间。<br />一般情况下，由于CHAR 数据类型长度固定，因此它比VARCHAR 类型的处理速度快。<br />     4、NVARCHAR<br />NVARCHAR数据类型的定义形式为NVARCHAR[ （n） ]。 它与VARCHAR 类型相似。不同的是，NVARCHAR数据类型采用UNICODE 标准字符集（Character Set）， n 的取值为1 到4000。</p>
		<p>4.3.6 文本和图形数据类型<br />    这类数据类型用于存储大量的字符或二进制数据。<br />     1、TEXT<br />TEXT数据类型用于存储大量文本数据，其容量理论上为1 到2的31次方-1 （2， 147， 483， 647）个字节，在实际应用时需要视硬盘的存储空间而定。<br />SQL Server 2000 以前的版本中，数据库中一个TEXT 对象存储的实际上是一个指针，它指向一个个以8KB （8192 个字节）为单位的数据页（Data Page）。 这些数据页是动态增加并被逻辑链接起来的。在SQL Server 2000 中，则将TEXT 和IMAGE 类型的数据直接存放到表的数据行中，而不是存放到不同的数据页中。 这就减少了用于存储TEXT 和IMA- GE 类型的空间，并相应减少了磁盘处理这类数据的I/O 数量。<br />    2 NTEXT<br />NTEXT数据类型与TEXT.类型相似不同的,是NTEXT 类型采用UNICODE 标准字符集(Character Set), 因此其理论容量为230-1(1, 073, 741, 823)个字节。<br />    3 IMAGE<br />IMAGE数据类型用于存储大量的二进制数据Binary Data。 其理论容量为2的31次方-1(2,147,483,647)个字节。其存储数据的模式与TEXT 数据类型相同。通常用来存储图形等OLE Object Linking and Embedding，对象连接和嵌入）对象。在输入数据时同BINARY数据类型一样，必须在数据前加上字符“0X”作为二进制标识</p>
		<p>4.3.7 日期和时间数据类型<br />    1 DATETIME<br />DATETIME 数据类型用于存储日期和时间的结合体。它可以存储从公元1753 年1 月1 日零时起到公元9999 年12 月31 日23 时59 分59 秒之间的所有日期和时间，其精确度可达三百分之一秒，即3.33 毫秒。DATETIME 数据类型所占用的存储空间为8 个字节。其中前4 个字节用于存储1900 年1 月1 日以前或以后的天数，数值分正负，正数表示在此日期之后的日期，负数表示在此日期之前的日期。后4 个字节用于存储从此日零时起所指定的时间经过的毫秒数。如果在输入数据时省略了时间部分，则系统将12:00:00:000AM作为时间缺省值：如果省略了日期部分，则系统将1900 年1 月1 日作为日期缺省值。<br />    2 SMALLDATETIME<br />SMALLDATETIME 数据类型与DATETIME 数据类型相似，但其日期时间范围较小，为从1900 年1 月1 日到2079 年6 月6：日精度较低，只能精确到分钟，其分钟个位上为根据秒数四舍五入的值,即以30 秒为界四舍五入。如：DATETIME 时间为14:38:30.283<br />时SMALLDATETIME 认为是14:39:00 SMALLDATETIME 数据类型使用4 个字节存储数据。其中前2 个字节存储从基础日期1900 年1 月1 日以来的天数，后两个字节存储此日零时起所指定的时间经过的分钟数。<br />    下面介绍日期和时间的输入格式<br />    日期输入格式<br />    日期的输入格式很多大致可分为三类： </p>
		<p>英文+数字格式<br />此类格式中月份可用英文全名或缩写，且不区分大小写；年和月日之间可不用逗号；<br />年份可为4 位或2 位；当其为两位时，若值小于50 则视为20xx 年，若大于或等于50 则<br />视为19xx 年；若日部分省略，则视为当月的1号。以下格式均为正确的日期格式：<br />June 21 2000 Oct 1 1999 January 2000 2000 February<br />2000 May 1 2000 1 Sep 99 June July 00 <br />数字+分隔符格式<br />允许把斜杠（/）、连接符（-）和小数点（.）作为用数字表示的年、月、日之间的分<br />隔符。如：<br />YMD：2000/6/22 2000-6-22 2000.6.22<br />MDY：3/5/2000 3-5-2000 3.5.2000<br />DMY：31/12/1999 31-12-1999 31.12.2000 <br />纯数字格式<br />纯数字格式是以连续的4 位6、位或8 位数字来表示日期。如果输入的是6 位或8 位<br />数字，系统将按年、月、日来识别，即YMD 格式，并且月和日都是用两位数字来表示：<br />如果输入的数字是4 位数，系统认为这4 位数代表年份,其月份和日缺省为此年度的1 月<br />1 日。如:<br />20000601---2000 年6 月1 日 991212---1999 年12 月12 日 1998---1998 年 <br />???? <br />时间输入格式<br />在输入时间时必须按“小时、分钟、秒、毫秒”的顺序来输入。在其间用冒号“：”隔开。但可将毫秒部分用小数点“.” 分，隔其后第一位数字代表十分之一秒，第二位数字代表百分之一秒，第三位数字代表千分之一秒。当使用12 小时制时用AM。am 和PM（pm）分别指定时间是午前或午后，若不指定，系统默认为AM。AM 与PM 均不区分大小写。如：<br />    3:5:7.2pm---下午3 时5 分7 秒200 毫秒<br />    10:23:5.123Am---上午10 时23 分5 秒123 毫秒<br />    可以使用SET DATEFORMAT 命令来设定系统默认的日期-时间格式。 </p>
		<p>4.3.8 货币数据类型<br />货币数据类型用于存储货币值。在使用货币数据类型时，应在数据前加上货币符号，系统才能辨识其为哪国的货币，如果不加货币符号，则默认为“￥”。各货币符号如图4-2所示。<br />    1 MONEY<br />MONEY 数据类型的数据是一个有4 位小数的DECIMAL 值，其取值从-2的63次方（-922，337，203，685，477.5808到2的63次方-1（+922，337，203，685，477.5807），数据精度为万分之一货币单位。MONEY 数据类型使用8个字节存储。<br /> <br />    2 SMALLMONEY<br />SMALLMONEY数据类型类似于MONEY 类型，但其存储的货币值范围比MONEY数据类型小,其取值从-214,748.3648到+214,748.3647,存储空间为4 个字节。</p>
		<p>4.3.9 特定数据类型<br />SQL Server 中包含了一些用于数据存储的特殊数据类型。<br />    1 TIMESTAMP<br />TIMESTAMP数据类型提供数据库范围内的惟一值此类型相当于BINARY8或VARBINARY（8），但当它所定义的列在更新或插入数据行时，此列的值会被自动更新，一个计数值将自动地添加到此TIMESTAMP数据列中。每个数据库表中只能有一个TIMESTAMP数据列。如果建立一个名为“TIMESTAMP”的列，则该列的类型将被自动设为TIMESTAMP数据类型。</p>
		<p>    2 UNIQUEIDENTIFIER<br />UNIQUEIDENTIFIER 数据类型存储一个16 位的二进制数字。此数字称为（GUIDGlobally Unique Identifier ，即全球惟一鉴别号）。此数字由SQLServer 的NEWID函数产生的全球惟一的编码，在全球各地的计算机经由此函数产生的数字不会相同。</p>
		<p>4.3.10 用户自定义数据类型<br />SYSNAME SYSNAME 数据类型是系统提供给用户的，便于用户自定义数据类型。它被定义为NVARCHAR（128），即它可存储128个UNICODE字符或256个一般字符。其具体使用方法请参见第7章“管理数据库表”中的“自定义数据类型”章节。</p>
		<p>4.3.11 新数据类型<br />SQL Server 2000 中增加了3 种数据类型：BIGINT、SQL_VARIANT和TABLE。其中BIGINT数据类型已在整数类型中介绍，下面介绍其余两种：<br />    1 SQL_VARIANT<br />SQL_VARIANT数据类型可以存储除文本、图形数据（TEXT、NTEXT、IMAGE）和TIMESTAMP类型数据外的其它任何合法的SQL Server数据。此数据类型大大方便了SQL Server的开发工作。<br />    2 TABLE<br />TABLE 数据类型用于存储对表或视图处理后的结果集。这一新类型使得变量可以存储一个表，从而使函数或过程返回查询结果更加方便快、捷其、使用请参见第13章“游标、视图和自定义函数”。</p>
		<p> </p>
<img src ="http://www.blogjava.net/jlin/aggbug/63051.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jlin/" target="_blank">fly</a> 2006-08-11 17:06 <a href="http://www.blogjava.net/jlin/articles/63051.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>