﻿<?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-文章分类-oracle</title><link>http://www.blogjava.net/shypwang/category/25146.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 25 Aug 2007 10:00:22 GMT</lastBuildDate><pubDate>Sat, 25 Aug 2007 10:00:22 GMT</pubDate><ttl>60</ttl><item><title>理解ORACLE数据库字符集</title><link>http://www.blogjava.net/shypwang/articles/139217.html</link><dc:creator>妖人</dc:creator><author>妖人</author><pubDate>Sat, 25 Aug 2007 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/shypwang/articles/139217.html</guid><wfw:comment>http://www.blogjava.net/shypwang/comments/139217.html</wfw:comment><comments>http://www.blogjava.net/shypwang/articles/139217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shypwang/comments/commentRss/139217.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shypwang/services/trackbacks/139217.html</trackback:ping><description><![CDATA[<strong>
<p class="title" align="center">理解ORACLE数据库字符集</p>
</strong>
<p align="center"><font face="楷体_GB2312">耿立宏<br>（中国科学院计算机网络信息中心，北京100080）</font></p>
<p><br><strong>一．引言</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>ORACLE数据库字符集，即Oracle全球化支持(Globalization
Support)，或即国家语言支持（NLS）其作用是用本国语言和格式来存储、处理和检索数据。利用全球化支持，ORACLE为用户提供自己熟悉的数据
库母语环境，诸如日期格式、数字格式和存储序列等。Oracle可以支持多种语言及字符集，其中oracle8i支持48种语言、76个国家地域、229
种字符集，而oracle9i则支持57种语言、88个国家地域、235种字符集。由于oracle字符集种类多，且在存储、检索、迁移oracle数据
时多个环节与字符集的设置密切相关，因此在实际的应用中，数据库开发和管理人员经常会遇到有关oracle字符集方面的问题。本文通过以下几个方面阐述，
对oracle字符集做简要分析</p>
<p><strong>二．字符集基本知识</strong></p>
<p><strong>2.1字符集<br></strong>&nbsp;&nbsp;&nbsp; 实质就是按照一定的字符编码方案，对一组特定的符号，分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。<br>&nbsp;&nbsp;&nbsp; Oracle的字符集命名遵循以下命名规则:<br>&nbsp;&nbsp;&nbsp; &lt;Language&gt;&lt;bit size&gt;&lt;encoding&gt;<br>&nbsp;&nbsp;&nbsp; 即:&nbsp; &lt;语言&gt;&lt;比特位数&gt;&lt;编码&gt;<br>&nbsp;&nbsp;&nbsp; 比如: ZHS16GBK表示采用GBK编码格式、16位（两个字节）简体中文字符集</p>
<p><strong>2.2字符编码方案<br></strong>2.2.1 单字节编码<br>&nbsp;&nbsp;&nbsp; （1）单字节7位字符集，可以定义128个字符，最常用的字符集为US7ASCII<br>&nbsp;&nbsp;&nbsp; （2）单字节8位字符集，可以定义256个字符，适合于欧洲大部分国家<br>&nbsp;&nbsp;&nbsp; 例如：WE8ISO8859P1(西欧、8位、ISO标准8859P1编码)<br>2.2.2 多字节编码<br>&nbsp;&nbsp;&nbsp; （1）变长多字节编码<br>&nbsp;&nbsp;&nbsp;&nbsp;某些字符用一个字节表示，其它字符用两个或多个字符表示，变长多字节编码常用于对亚洲语言的支持，&nbsp;&nbsp; 例如日语、汉语、印地语等<br>&nbsp;&nbsp;&nbsp; 例如：AL32UTF8（其中AL代表ALL,指适用于所有语言）、zhs16cgb231280<br>&nbsp;&nbsp;&nbsp; （2）定长多字节编码<br>&nbsp;&nbsp;&nbsp; 每一个字符都使用固定长度字节的编码方案，目前oracle唯一支持的定长多字节编码是AF16UTF16，也是仅用于国家字符集<br>2.2.3 unicode编码<br>&nbsp;&nbsp;&nbsp;
Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案，也就是说Unicode为每一个字符提供唯一的编码。UTF-16是
unicode的16位编码方式，是一种定长多字节编码，用2个字节表示一个unicode字符，AF16UTF16是UTF-16编码字符集。<br>&nbsp;&nbsp;&nbsp; UTF-8是unicode的8位编码方式，是一种变长多字节编码，这种编码可以用1、2、3个字节表示一个unicode字符，AL32UTF8，UTF8、UTFE是UTF-8编码字符集</p>
<p><strong>2.3 字符集超级<br></strong>&nbsp;&nbsp;&nbsp; 当一种字符集（字符集A）的编码数值包含所有另一种字符集（字符集B）的编码数值，并且两种字符集相同编码数值代表相同的字符时，则字符集A是字符集B的超级，或称字符集B是字符集A的子集。<br>&nbsp;&nbsp;&nbsp;
Oracle8i和oracle9i官方文档资料中备有子集-超级对照表（subset-superset
pairs），例如：WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式，因此有许多
字符集是US7ASCII的超集，例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。</p>
<p><strong>2.4 数据库字符集（oracle服务器端字符集）<br></strong>&nbsp;&nbsp;&nbsp; 数据库字符集在创建数据库时指定，在创建后通常不能更改。在创建数据库时，可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。<br>2.4.1字符集<br>&nbsp;&nbsp;&nbsp; (1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据<br>&nbsp;&nbsp;&nbsp; (2)用来标示诸如表名、列名以及PL/SQL变量等<br>&nbsp;&nbsp;&nbsp; (3)用来存储SQL和PL/SQL程序单元等<br>2.4.2国家字符集：<br>&nbsp;&nbsp;&nbsp; (1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据<br>&nbsp;&nbsp;&nbsp;
(2)国家字符集实质上是为oracle选择的附加字符集，主要作用是为了增强oracle的字符处理能力，因为NCHAR数据类型可以提供对亚洲使用定
长多字节编码的支持，而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义，只能在unicode编码中的AF16UTF16和UTF8
中选择，默认值是AF16UTF16<br>2.4.3查询字符集参数<br>&nbsp;&nbsp;&nbsp; 可以查询以下数据字典或视图查看字符集设置情况<br>&nbsp;&nbsp;&nbsp; nls_database_parameters、props$、v$nls_parameters<br>&nbsp;&nbsp;&nbsp; 查询结果中NLS_CHARACTERSET表示字符集，NLS_NCHAR_CHARACTERSET表示国家字符集<br>2.4.4修改数据库字符集<br>&nbsp;&nbsp;&nbsp;
按照上文所说，数据库字符集在创建后原则上不能更改。如果需要修改字符集，通常需要导出数据库数据，重建数据库，再导入数据库数据的方式来转换，或通过
ALTER DATABASE CHARACTER
SET语句修改字符集，但创建数据库后修改字符集是有限制的，只有新的字符集是当前字符集的超集时才能修改数据库字符集，例如UTF8是US7ASCII
的超集，修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。</p>
<p><strong>2.5 客户端字符集（NLS_LANG参数）</strong><br>2.5.1客户端字符集含义<br>&nbsp;&nbsp;&nbsp; 客户端字符集定义了客户端字符数据的编码方式，任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用，例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。<br>2.5.2 NLS_LANG参数格式<br>&nbsp;&nbsp;&nbsp; NLS_LANG=&lt;language&gt;_&lt;territory&gt;.&lt;client character set&gt; <br>&nbsp;&nbsp;&nbsp; Language:显示oracle消息,校验，日期命名<br>&nbsp;&nbsp;&nbsp; Territory：指定默认日期、数字、货币等格式<br>&nbsp;&nbsp;&nbsp; Client character set：指定客户端将使用的字符集<br>&nbsp;&nbsp;&nbsp; 例如：NLS_LANG=AMERICAN_AMERICA.US7ASCII&nbsp; <br>&nbsp;&nbsp;&nbsp; AMERICAN是语言，AMERICA是地区，US7ASCII是客户端字符集<br>2.5.3客户端字符集设置方法<br>&nbsp;&nbsp;&nbsp;&nbsp; 1)UNIX环境<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $NLS_LANG=&#8220;simplified chinese&#8221;_china.zhs16gbk<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $export NLS_LANG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编辑oracle用户的profile文件<br>&nbsp;&nbsp;&nbsp; 2)Windows环境<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编辑注册表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME0<br>2.5.4 NLS参数查询<br>&nbsp;&nbsp;&nbsp; Oracle提供若干NLS参数定制数据库和用户机以适应本地格式，例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等，可以通过查询以下数据字典或v$视图查看。<br>&nbsp;&nbsp;&nbsp; NLS_DATABASE_PARAMETERS--显示数据库当前NLS参数取值，包括数据库字符集取值<br>&nbsp;&nbsp;&nbsp; NLS_SESSION_PARAMETERS--显示由NLS_LANG 设置的参数，或经过alter session 改变后的参数值（不包括由NLS_LANG 设置的客户端字符集）<br>&nbsp;&nbsp;&nbsp; NLS_INSTANCE_PARAMETE--显示由参数文件init&lt;SID&gt;.ora 定义的参数V$NLS_PARAMETERS--显示数据库当前NLS参数取值<br>2.5.5修改NLS参数<br>&nbsp;&nbsp;&nbsp; 使用下列方法可以修改NLS参数<br>&nbsp;&nbsp;&nbsp; （1）修改实例启动时使用的初始化参数文件<br>&nbsp;&nbsp;&nbsp; （2）修改环境变量NLS_LANG<br>&nbsp;&nbsp;&nbsp; （3）使用ALTER SESSION语句，在oracle会话中修改<br>&nbsp;&nbsp;&nbsp; （4）使用某些SQL函数<br>&nbsp;&nbsp;&nbsp; NLS作用优先级别：Sql function&gt;alter session&gt;环境变量或注册表&gt;参数文件&gt;数据库默认参数</p>
<p><strong>三．导入/导出与字符集转换</strong></p>
<p><strong>3.1 EXP/IMP<br></strong>&nbsp;&nbsp;&nbsp; Export 和 Import
是一对读写Oracle数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import
把这些文件中的数据读到Oracle
数据库中，由于使用exp/imp进行数据迁移时，数据从源数据库到目标数据库的过程中有四个环节涉及到字符集，如果这四个环节的字符集不一致，将会发生
字符集转换。</p>
<p>EXP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p align="center"><img  src="http://www.csdb.cn/upload/112.bmp" border="0"></p>
<p>IMP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p align="center"><img  src="http://www.csdb.cn/upload/113.bmp" border="0"></p>
<p>&nbsp;&nbsp;&nbsp; 四个字符集是<br>&nbsp;&nbsp; （1）源数据库字符集 <br>&nbsp;&nbsp; （2）Export过程中用户会话字符集（通过NLS_LANG设定）<br>&nbsp;&nbsp; （3）Import过程中用户会话字符集（通过NLS_LANG设定）<br>&nbsp;&nbsp; （4）目标数据库字符集</p>
<p><strong>3.2导出的转换过程<br></strong>&nbsp;&nbsp;&nbsp; 在Export过程中，如果源数据库字符集与Export用户会话字符集不一致，会发生字符集转换，并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。<br>例:
如果源数据库使用ZHS16GBK，而Export用户会话字符集使用US7ASCII，由于ZHS16GBK是16位字符集,而US7ASCII是7位
字符集，这个转换过程中，中文字符在US7ASCII中不能够找到对等的字符，所以所有中文字符都会丢失而变成&#8220;??
&#8221;形式，这样转换后生成的Dmp文件已经发生了数据丢失。<br>因此如果想正确导出源数据库数据，则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集</p>
<p><strong>3.3导入的转换过程</strong><br>&nbsp;&nbsp;&nbsp; （1）确定导出数据库字符集环境<br>&nbsp;&nbsp;&nbsp; 通过读取导出文件头，可以获得导出文件的字符集设置<br>&nbsp;&nbsp;&nbsp; （2）确定导入session的字符集，即导入Session使用的NLS_LANG环境变量<br>&nbsp;&nbsp;&nbsp; （3）IMP读取导出文件<br>&nbsp;&nbsp;&nbsp; 读取导出文件字符集ID，和导入进程的NLS_LANG进行比较<br>&nbsp;&nbsp;&nbsp; （4）如果导出文件字符集和导入Session字符集相同，那么在这一步骤内就不需要转换，如果不同，就需要把数据转换为导入Session使用的字符集。可以看出，导入数据到数据库过程中发生两次字符集转换<br>&nbsp;&nbsp;&nbsp; 第一次:导入文件字符集与导入Session使用的字符集之间的转换，如果这个转换过程不能正确完成，Import向目标数据库的导入过程也就不能完成。<br>&nbsp;&nbsp;&nbsp; 第二次:导入Session字符集与数据库字符集之间的转换。<br>&nbsp;&nbsp;&nbsp;
然而,oracle8i的这种转换只能在单字节字符集之间进行,oracle8i导入Session不支持多字节字符集之间的转换，因此为了避免第一次转
换，导入Session使用的NLS_LANG与导出文件字符集相同，第二次转换（通过SQL*Net）支持任何两种字符集。以上情况在Oracle9i
中略有不同</p>
<p><strong>四．乱码问题</strong></p>
<p>&nbsp;&nbsp;&nbsp; oracle在数据存储、迁移过程中经常发生字符乱码问题，归根到底是由于字符集使用不当引起。下面以使用客户端sqlplus向数据库插入数据和导入/导出（EXP/IMP）过程为例，说明乱码产生的原因。</p>
<p><strong>4.1使用客户端sqlplus向数据库存储数据</strong><br>&nbsp;&nbsp;&nbsp; 这个过程存在3个字符集设置<br>&nbsp;&nbsp;&nbsp; （1）客户端应用字符集<br>&nbsp;&nbsp;&nbsp; （2）客户端NLS_LANG参数设置<br>&nbsp;&nbsp;&nbsp; （3）服务器端数据库字符集(Character Set)设置<br>&nbsp;&nbsp;&nbsp;
客户端应用sqlplus中能够显示什么样的字符取决于客户端操作系统语言环境(客户端应用字符集)，但在应用中录入这些字符后，这些字符能否在数据库中
正常存储，还与另外两个字符集设置紧密相关，其中客户端NLS_LANG参数主要用于字符数据传输过程中的转换判断。常见的乱码大致有两种情形：<br>&nbsp;&nbsp;&nbsp; （1）汉字变成问号&#8220;？&#8221;；<br>当从字符集A 转换成字符集B时，如果转换字符之间不存在对应关系，NLS_LANG使用替代字符&#8220;？&#8221;替代无法映射的字符<br>&nbsp;&nbsp;&nbsp; （2）汉字变成未知字符（虽然有些是汉字，但与原字符含义不同）<br>转换存在对应关系，但字符集A 中的字符编码与字符集B 中的字符编码代表不同含义</p>
<p><strong>4.2发生乱码原因</strong>&nbsp;<br>&nbsp;&nbsp; &nbsp;乱码产生是由于几个字符集之间转换不匹配造成，分以下几种情况：<br>&nbsp;&nbsp;&nbsp; （注：字符集之间如果不存在子集、超集对应关系时的情况不予考虑，因为这种情况下字符集之间转换必产生乱码）&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp; 1）服务器端数据库字符集与客户端应用字符集相同，与客户端NLS_LANG参数设置不同<br>&nbsp;&nbsp;&nbsp; 如果客户端NLS_LANG字符集是其它两种字符集的子集，转换过程将出现乱码。<br>&nbsp;&nbsp;&nbsp; 解决方法：将三种字符集设置成同一字符集，或NLS_LANG字符集是其它两种字符集的超集<br>&nbsp;&nbsp;&nbsp; 2）服务器端数据库字符集与客户端NLS_LANG参数设置相同，与客户端应用字符集不同<br>&nbsp;&nbsp;&nbsp; 如果客户端应用字符集是其它两种字符集的超集时，转换过程将出现乱码，但对于单字节编码存储中文问题，可参看本文第5章节的分析<br>&nbsp;&nbsp;&nbsp; 3）客户端应用字符集、客户端NLS_LANG参数设置、服务器端数据库字符集互不相同<br>&nbsp;&nbsp; &nbsp;此种情况较为复杂，但三种字符集之间只要有不能转换的字符，则必产生乱码</p>
<p><strong>4.3导入/导出过程出现乱码原因</strong><br>&nbsp;&nbsp;&nbsp; 这个过程存在4个字符集设置，在3.1章节中已分析<br>&nbsp;&nbsp; （1）源数据库字符集<br>&nbsp;&nbsp; （2）EXP过程中NLS_LANG参数 <br>&nbsp;&nbsp; （3）IMP过程中NLS_LANG参数<br>&nbsp;&nbsp; （4）目标数据库字符集<br>&nbsp;&nbsp;&nbsp; 出现乱码原因<br>&nbsp;&nbsp;&nbsp; 1）当源数据库字符集不等于EXP过程中NLS_LANG参数，且源数据库字符集是EXP过程中NLS_LANG的子集，才能保证导出文件正确，其他情况则导出文件字符乱码<br>&nbsp;&nbsp;&nbsp; 2）EXP过程中NLS_LANG字符集不等于IMP过程中NLS_LANG字符集，且EXP过程中NLS_LANG字符集是IMP过程中NLS_LANG字符集的子级, 才能保证第一次转换正常，否则第一次转换中出现乱码。<br>&nbsp;&nbsp;&nbsp; 3）如果第一次转换正常，IMP过程中NLS_LANG字符集是目标数据库字符集的子集或相同，才能保证第二次转换正常，否则则第二次转换中出现乱码</p>
<p><strong>五．单字节编码存储中文问题</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>由于历史的原因，早期的oracle没有中文字符集（如oracle6、oracle7、
oracle7.1）,但有的用户从那时起就使用数据库了，并用US7ASCII字符集存储了中文，或是有的用户在创建数据库时，不考虑清楚，随意选择一
个默认的字符集，如WE8ISO8859P1或US7ASCII，而这两个字符集都没有汉字编码，虽然有些时候选用这种字符集好象也能正常使用，但用这种
字符集存储汉字信息从原则上说就是错误的，它会给数据库的使用与维护带来一系列的麻烦。<br>&nbsp;&nbsp;&nbsp;
正常情况下，要将汉字存入数据库，数据库字符集必须支持中文，而将数据库字符集设置为US7ASCII等单字节字符集是不合适的。US7ASCII字符集
只定义了128个符号，并不支持汉字。另外，如果在SQL*PLUS中能够输入中文，操作系统缺省应该是支持中文的，但如果在NLS_LANG中的字符集
设置为US7ASCII，显然也是不正确的，它没有反映客户端的实际情况。但在实际应用中汉字显示却是正确的，这主要是因为Oracle检查数据库与客户
端的字符集设置是同样的，那么数据在客户与数据库之间的存取过程中将不发生任何转换，但是这实际上导致了数据库标识的字符集与实际存入的内容是不相符的。
而在SELECT的过程中，Oracle同样检查发现数据库与客户端的字符集设置是相同的，所以它也将存入的内容原封不动地传送到客户端，而客户端操作系
统识别出这是汉字编码所以能够正确显示。<br>&nbsp;&nbsp;&nbsp; 在这个例子中，数据库与客户端都没有设置成中文字符集，但却能正常显示中文，从应用的角度看好象没问题。然而这里面却存在着极大的隐患，比如在应用length或substr等字符串函数时，就可能得到意外的结果。<br>&nbsp;&nbsp;&nbsp;
对于早期使用US7ASCII字符集数据库的数据迁移到oracle8i/9i中（使用zhs16gbk），由于原始数据已经按照US7ASCII格式存
储，对于这种情况，可以通过使用Oracle8i的导出工具，设置导出字符集为US7ASCII，导出后使用UltraEdit等工具打开dmp文件，修
改第二、三字符，修改 0001 为0354,这样就可以将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。</p>
<p><strong>六．结束语</strong></p>
<p>&nbsp;&nbsp;&nbsp; 为了避免在数据库迁移过程中由于字符集不同导致的数据损失，oracle提供了字符集扫描工具（character set
scanner），通过这个工具我们可以测试在数据迁移过程中由于字符集转换可能带来的问题，然后根据测试结果，确定数据迁移过程中最佳字符集解决方案。</p>
<p><br><strong>参考文献</strong><br>[1]Biju Thomas , Bob Bryla《oracle9i DBA基础I 学习指南》电子工业出版社 2002<br>[2]网站 <a  href="http://www.itpub.net/">http://www.itpub.net</a><br></p><img src ="http://www.blogjava.net/shypwang/aggbug/139217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shypwang/" target="_blank">妖人</a> 2007-08-25 09:10 <a href="http://www.blogjava.net/shypwang/articles/139217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动态建表的权限分析(上)</title><link>http://www.blogjava.net/shypwang/articles/138917.html</link><dc:creator>妖人</dc:creator><author>妖人</author><pubDate>Thu, 23 Aug 2007 11:19:00 GMT</pubDate><guid>http://www.blogjava.net/shypwang/articles/138917.html</guid><wfw:comment>http://www.blogjava.net/shypwang/comments/138917.html</wfw:comment><comments>http://www.blogjava.net/shypwang/articles/138917.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shypwang/comments/commentRss/138917.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shypwang/services/trackbacks/138917.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 动态建表的权限分析(上)一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 引言1、&nbsp; 目的最近有很多人通过各种方式和途径来咨询我在使用Oracle的过程中，明明用户拥有create table的权限，却无法在pl/sql完成动态建表和索引的工作，并经常出现类似如下提示：ERROR 位于第 1 行:ORA-01031: 权限不...&nbsp;&nbsp;<a href='http://www.blogjava.net/shypwang/articles/138917.html'>阅读全文</a><img src ="http://www.blogjava.net/shypwang/aggbug/138917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shypwang/" target="_blank">妖人</a> 2007-08-23 19:19 <a href="http://www.blogjava.net/shypwang/articles/138917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle sql 学习笔记</title><link>http://www.blogjava.net/shypwang/articles/138788.html</link><dc:creator>妖人</dc:creator><author>妖人</author><pubDate>Thu, 23 Aug 2007 04:31:00 GMT</pubDate><guid>http://www.blogjava.net/shypwang/articles/138788.html</guid><wfw:comment>http://www.blogjava.net/shypwang/comments/138788.html</wfw:comment><comments>http://www.blogjava.net/shypwang/articles/138788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shypwang/comments/commentRss/138788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shypwang/services/trackbacks/138788.html</trackback:ping><description><![CDATA[<pre><tt><tt>select * from v$version  --查看版本<br>-----------------------------------------------------------------------------------<br>create table tempppp <br>(exception number(1)<br>)<br>insert into tempppp values(1)<br><br>select "EXCEPTION" from tempppp<br>select "exception" from tempppp   --failed<br>  引征区分大小写，数据字典里都为大写<br>select exception from tempppp<br>insert into tempppp values('2')<br><br>-----------------------------------------------------------------------------------<br><br>&lt;&lt;ppp&gt;&gt;<br>declare <br> Orgid number(19):=-1;--变量名不要和表列名相同<br> v_tmp number(19);<br>begin<br>     select count(orgid)  into v_tmp from organization where<br> orgid=Orgid;<br>     Dbms_Output.put_line(v_tmp);<br>     select count(orgid)  into v_tmp from organization where<br> orgid=ppp.Orgid;<br>end;<br><br>--------------------------------------------------------------------------<br>declare <br> inxx varchar(2):='N ';--都为定长采用填充空格式<br> --inxx varchar(2):='N ';--有一个为变长采用非填充空格式<br> v_tmp number(19);<br>begin<br>     select count(1)  into v_tmp from dcperioddetail where inuse=inxx;<br>     Dbms_Output.put_line(v_tmp);<br>     <br>end;<br><br><br>----------------------------------------------------------------------------<br>--伪列<br>select productseq.nextval from dual<br>select productseq.currval from dual<br>  --只有发出至少一条nextval才能在会话中访问curval<br><br>select rowid from product<br>select rowidtochar(rowid) from product<br><br>select prodid from product where rownum&lt;3<br><br><br>SELECT contactid ,level<br>FROM contact <br>--where contactid=100000020<br>START WITH contactid = (<br>select b.contactid <br>from usr b <br>where b.userid=1) <br>CONNECT BY parentcontactid = PRIOR contactid<br><br>------------------------------------------------------------------------------------<br>--常用函数<br>select upper(prodcode) from product where prodcode like 'qs040089'<br>--substr<br>select substr('qs040089',0) from dual<br>select substr('qs040089',1) from dual<br>select substr('qs040089',2) from dual<br>select substr('qs040089',-3) from dual<br>select substr('qs040089',1,1.5) from dual<br><br>--instr<br>select instr('qs040089','04') from dual<br>select instr('qs040089','04',4) from dual<br>select instr('qs040089','04',-1) from dual<br>--length<br>select length('qs040089') from dual<br><br>--decode<br>select decode(prodcode,'qs040089',1,2) from product where prodcode like<br> 'qs040089'<br><br>--trunc<br>select trunc(datelastupdated),datelastupdated from product where<br> prodcode like 'qs040089'<br><br>--round  <br>select round(datelastupdated),datelastupdated from product where<br> prodcode like 'qs040089'<br><br>--to_char<br>select to_char(sysdate,'DD-MM-YY HH24:MI:SS') from dual<br><br>--to_date<br>declare <br>        v_CurrentDate DATE;<br>begin<br>     <br>     v_CurrentDate :=to_date('11 07, 1973','MM DD, YYYY');<br>     Dbms_Output.put_line(v_CurrentDate);<br>end;<br><br>--nullif<br>select nullif(1,12) from dual<br>select nullif(12,1) from dual<br>select nullif(12,12) from dual<br><br>--nvl<br>select nvl(2,1) from dual<br>select nvl(null,1) from dual<br><br>select user from dual<br>select USERENV('TERMINAL'),USERENV('LANGUAGE') from dual<br><br><br>--CURSOR<br> 游标----------------------------------------------------------------<br><br><br><br>--sql<br> 游标------------------------------------------------------------------<br>begin <br>      update product<br>      set prodcode='8800000000000'<br>      where prodcode='qs04008911111';<br>      <br>      if SQL%NOTFOUND THEN<br>         DBMS_OUTPUT.put_line(11111);<br>      end if;<br>end;<br><br>begin <br>      update product<br>      set prodcode='8800000000000'<br>      where prodcode='qs04008911111';<br>      <br>      if SQL%ROWCOUNT=0 THEN<br>         DBMS_OUTPUT.put_line(11111);<br>      end if;<br>end;<br> <br>DECLARE <br>        v_tmp product%rowtype;<br>begin <br>      select *  into v_tmp from product where prodid=-1;<br>      --SELECT INTO 未找到会报错！<br>      if SQL%notfound THEN<br>         DBMS_OUTPUT.put_line(222222);<br>      end if;<br>      exception<br>        when NO_DATA_FOUND then<br>               DBMS_OUTPUT.put_line(3333333);<br>end;<br><br><br><br><br>-- for update<br>select * from productlang a for update of productlangid <br><br>select * from productlang a for update <br>select * from productlang a for update nowait<br>select * from productlang a for update wait 10<br><br><br>declare <br>  cursor c_allproduct is <br>         select * from product <br>         for update;--for update不能在循环中使用commit<br>  v_oneprd c_allproduct%rowtype;<br>begin<br>  open c_allproduct;<br>  fetch c_allproduct into v_oneprd;<br>  commit;--for update不能在循环中使用commit<br>  fetch c_allproduct into v_oneprd;<br>end;<br><br><br>declare <br>  cursor c_allproduct is <br>         select * from product ;<br>         <br>  v_oneprd c_allproduct%rowtype;<br>begin<br>  open c_allproduct;<br>   <br>  loop<br>  fetch c_allproduct into v_oneprd;<br>  exit when c_allproduct%notfound;<br>  commit;<br>  <br> <br>  end loop;<br>  close c_allproduct;<br>  --close c_allproduct;-- INVALID_CURSOR<br>end;<br><br><br>declare <br>  type t_ddd is ref cursor return product%rowtype;<br>  v_CursorVar t_ddd;<br>begin<br>     open v_CursorVar for select * from<br> organization;--类型与游标变量返回类型不同<br>     close v_CursorVar;<br>end;<br><br><br>--错误处理--------------------------------------------------------------------------<br>declare v_NumStudents number;<br>begin<br>     select count(1) <br>     into v_NumStudents<br>     from sstudents;--编译错误<br>end;<br><br><br><br>declare <br>  x number:=1;<br>  y number:=2;<br>  z number:=3;<br>begin<br>     y:=x/0;--运行时异常<br>exception<br> when others then <br>   dbms_output.put_line(sqlcode||sqlerrm);<br>end;<br><br><br>declare<br>  type t_NumberTableType is table of number<br>    index by binary_integer;<br>  v_NumberTable t_NumberTableType;<br>  v_temp number;<br>begin<br>  v_temp:=v_NumberTable(1);--NO_DATA_FOUND<br>end;   <br><br>DECLARE <br>  v_TempVar varchar2(2);<br>begin<br>  v_TempVar:='111';--NUMERIC OR VALUE ERROR<br>end;<br><br><br>declare <br> e_TooManyStudents exception;--自定义异常<br> v_currentStudents number(4);<br> v_Max number(4);<br>begin<br>  <br>    select 10,count(1)  into v_Max,v_currentStudents   from product ;<br>    if v_Max&lt;v_currentStudents then<br>     raise e_TooManyStudents;<br>    end if; <br>    exception <br>      when e_TooManyStudents then<br>          dbms_output.put_line(sqlcode||' '||sqlerrm);<br>  <br>end;<br><br>--7.1.3<br>declare <br>v_xxx varchar2(200);<br>begin<br>v_xxx :=sqlerrm(1);<br>  dbms_output.put_line('sqlerrm: '''||sqlerrm||'''');<br>   dbms_output.put_line('sqlerrm(0): '''||sqlerrm(0)||'''');<br>   dbms_output.put_line('sqlerrm(100): '''||sqlerrm(100)||'''');<br>   dbms_output.put_line('sqlerrm(-1): '''||sqlerrm(-1)||'''');<br>   dbms_output.put_line('sqlerrm(-54): '''||sqlerrm(-54)||'''');<br>   dbms_output.put_line('sqlerrm(10): '''||sqlerrm(10)||'''');<br>end;<br><br>--7.1.4<br>declare <br> e_missingNull exception;<br> pragma exception_init(e_missingNull,-1400); --编译指示<br>begin<br>  insert into dictionary(dictionaryid) values(null);<br>exception<br> when e_missingNull then<br>  dbms_output.put_line(sqlcode||' '||sqlerrm);--不显示"user-defined<br> exception"<br>end;<br><br><br>--7.1.5<br><br>declare <br> e_TooManyStudents exception;--自定义异常<br> v_currentStudents number(4);<br> v_Max number(4);<br>begin<br>  <br>    select 10,count(1)  into v_Max,v_currentStudents   from product ;<br>    if v_Max&lt;v_currentStudents then<br>     --raise e_TooManyStudents;<br>     raise_application_error(-20001,'long long ago there was an<br> idiot!');<br>    end if; <br>    exception <br>      when others then<br>          dbms_output.put_line(sqlcode||' '||sqlerrm);<br>          --delete jjl;<br>          --commit;<br>          --raise;<br>  <br>end;<br><br>begin<br>     declare <br>             e_TooManyStudents exception;--自定义异常<br>     begin<br>          raise e_TooManyStudents;<br>     end;<br>exception <br> when e_TooManyStudents then --自定义异常超出作用域<br>   raise;<br>end;<br><br><br>declare <br> v_Tmp number(6):='ABC';--声明中的错误直接传到最外层<br>begin<br>  null;--begin后面一定要有东西<br>  exception<br>   when others then<br>     dbms_output.put_line(sqlcode||' '||sqlerrm);<br>end;<br><br><br>begin<br>  declare <br>          v_Tmp number(6):='ABC';--声明中的错误直接传到最外层<br>  begin<br>       null;--begin后面一定要有东西<br>        exception<br>                 when others then<br>                 dbms_output.put_line('2222');<br>  end;<br>  exception<br>   when others then<br>     dbms_output.put_line(sqlcode||' '||sqlerrm);<br>end;<br><br><br><br><br><br>--集合--------------------------------------------------------------------------------<br>declare <br> type NumberTab is table of number index by binary_integer;<br> v_Numbers NumberTab;<br>begin<br> for v_Count in 1..10 loop<br>     v_Numbers(v_Count):=v_Count;<br> end loop;<br> <br> for v_Count in 1..10 loop<br>      dbms_output.put_line('number['||to_char(v_count)||']='||'<br> '||v_Numbers(v_Count));<br> end loop;<br> <br> dbms_output.put_line('number['||to_char(11)||']='||'<br> '||v_Numbers(11));<br> <br> exception <br>  when no_data_found then<br>    dbms_output.put_line(sqlcode||' '||sqlerrm);<br>end;<br><br><br><br><br>declare <br> type ProdTab is table of product%rowtype index by binary_integer;<br> v_Prods ProdTab;<br>begin<br> if v_Prods is null then<br>  dbms_output.put_line('v_Prods is null');<br> end if;<br> select * <br> into v_Prods(2000001160)<br> from product<br> where prodid=2000001160; <br> <br> dbms_output.put_line('the code of prod['||to_char(2000001160)||']='||'<br> '||v_Prods(2000001160).prodcode);<br> <br> exception <br>  when no_data_found then<br>    dbms_output.put_line(sqlcode||' '||sqlerrm);<br>end;<br><br>--嵌套表构造器初始化<br>declare <br> type NumberTab is table of number;<br> v_Tab1 NumberTab:=NumberTab();<br> v_Tab2 NumberTab:=NumberTab(2);<br> v_Tab3 NumberTab;<br>begin<br>   if v_Tab1 is null then<br>     dbms_output.put_line('v_Tab1 is Null');<br>   else <br>      dbms_output.put_line('v_Tab1 is not Null');<br>   end if;<br>   --v_Tab1(1):=1;--wrong 元素不存在  subscript beyond count<br>   if v_Tab2 is null then<br>     dbms_output.put_line('v_Tab2 is Null');<br>   else <br>      dbms_output.put_line('v_Tab2 is not Null ' || v_Tab2(1));<br>   end if;<br>   <br>   if v_Tab3 is null then<br>     dbms_output.put_line('v_Tab3 is Null');<br>   else <br>      dbms_output.put_line('v_Tab3 is not Null');<br>   end if;<br>end;<br><br><br><br>declare <br>  type Numbers is array(20) of number(3);--可变数组<br>  <br>  v_NullList Numbers;<br>  v_List1 Numbers:=Numbers(1,2);--数组大小由构造器决定<br>  v_List2 Numbers:=Numbers(null);<br>begin<br>  if v_NullList is null then<br>    dbms_output.put_line('v_NullList is Null');<br>  end if;<br>  <br>  if v_List1(1) is null then<br>    dbms_output.put_line('v_List1(1) is Null');<br>  end if;<br>  <br>  if v_List2(1) is null then<br>    dbms_output.put_line('v_List2(1) is Null');<br>  end if;<br>  <br>  --v_List1(3):=1;--  subscript beyond count 数组大小由构造器决定<br>  v_List1.extend;<br>  v_List1(3):=1;<br>  <br>end;<br>  <br>  <br>  <br>  --多层集合<br>declare<br>  type t_Numbers is table of number index by binary_integer;<br>  type t_MultiNumbers is table of t_Numbers index by binary_integer;<br>  <br>  type t_MultiArray is varray(10) of t_Numbers;<br>  type t_MultiNested is table of t_Numbers;<br>  <br>  v_MultiNumbers t_MultiNumbers;<br>begin<br>  v_MultiNumbers(1)(1):=1;<br>end;<br><br><br><br>-- 过程，函数，包<br>create or replace procedure ModeTest(p_InParam in number,p_OutParam out<br> number<br>                  ,p_InOutParam in out number)is<br>v_localVariable number :=0;<br>begin<br>     dbms_output.put_line('Inside ModeTest');<br>     if(p_InParam is null) then<br>       dbms_output.put_line('p_InParam is null');<br>     else<br>       dbms_output.put_line('p_InParam is '||p_InParam);<br>     end if;<br>     <br>     if(p_OutParam is null) then<br>       dbms_output.put_line('p_OutParam is null');<br>     else<br>       dbms_output.put_line('p_OutParam is '||p_OutParam);<br>     end if;<br>     <br>     if(p_InOutParam is null) then<br>       dbms_output.put_line('p_InOutParam is null');<br>     else<br>       dbms_output.put_line('p_InOutParam is '||p_InOutParam);<br>     end if;<br>     <br>     v_localVariable := p_InParam; --legal<br>     --p_InParam:=7;--illegal<br>     p_OutParam:=7;<br>     v_localVariable:=p_OutParam;--possibly illegal,illegal prior to<br> 7.3.4<br>     v_localVariable:=p_InOutParam;<br>     p_InOutParam:=8;<br>     <br>     dbms_output.put_line('at the end of ModeTest');<br>     if(p_InParam is null) then<br>       dbms_output.put_line('p_InParam is null');<br>     else<br>       dbms_output.put_line('p_InParam is '||p_InParam);<br>     end if;<br>     <br>     if(p_OutParam is null) then<br>       dbms_output.put_line('p_OutParam is null');<br>     else<br>       dbms_output.put_line('p_OutParam is '||p_OutParam);<br>     end if;<br>     <br>     if(p_InOutParam is null) then<br>       dbms_output.put_line('p_InOutParam is null');<br>     else<br>       dbms_output.put_line('p_InOutParam is '||p_InOutParam);<br>     end if;<br>     <br>end ModeTest;<br><br>declare <br>  v_a number :=1;<br>  v_b number :=2;<br>begin<br> ModeTest(1,v_a,v_b);<br>end;<br><br>drop procedure ModeTest;<br><br>-----------------------<br><br>create or replace procedure ParamLength(p_param1 in out varchar2,<br>                          p_param2 in out number)is<br>begin<br>  p_param1:='abcdefghijklmno';<br>  p_param2:=12.3;<br>end;<br><br>declare <br>  v_a varchar(40);<br> --v_a varchar(10);--形参约束从实际参数获得<br> v_b number(7,3);<br>begin<br> ParamLength(v_a,v_b);<br>end;<br> <br>drop procedure ParamLength;<br>-------------------------<br><br>create or replace procedure RaiseError(<br>       p_Raise in boolean,<br>       p_ParamA out number)as<br>begin<br>     p_ParamA:=7;<br>     <br>     if p_Raise then<br>        raise dup_val_on_index;--当存储过程发生错误时,out<br> inout形式参数值不会返回给实际参数<br>     else<br>      return;<br>     end if;<br>end RaiseError;<br><br><br>create or replace procedure RaiseError(<br>       p_Raise in boolean,<br>       p_ParamA out nocopy number)as--传引用,即使报错,值也会被修改<br>begin<br>     p_ParamA:=7;<br>     <br>     if p_Raise then<br>        raise dup_val_on_index;<br>     else<br>      return;<br>     end if;<br>end RaiseError;<br><br><br>declare v_tmp number:=1;<br>--declare v_tmp number(2):=1;--实际参数受精度可读或not<br> null约束，nocopy无效<br>begin<br>  dbms_output.put_line('initial value: '||v_tmp);<br>  raiseError(false,v_tmp);<br>  dbms_output.put_line('after false: '||v_tmp);<br>  v_tmp:=2;<br>  dbms_output.put_line('before true: '||v_tmp);<br>  raiseError(true,v_tmp);<br>  <br>exception <br>  when others then<br>    dbms_output.put_line('after unsuccessful: '||v_tmp);<br>end;<br><br>drop procedure RaiseError;<br><br>------------------------------<br>create or replace procedure DefaultTest(<br>  p_ParameterA number default 10,<br>  p_ParameterB varchar2 default 'abcdef',<br>  p_ParameterC date default sysdate)as<br>begin<br>  dbms_output.put_line(<br>    'A: '|| p_ParameterA||<br>    ' B: '||p_ParameterB||<br>    'C:'||to_char(p_ParameterC,'DD-MON-YYYY')<br>    );<br>end;<br><br>begin<br>  DefaultTest(p_ParameterA=&gt;7,p_ParameterC =&gt;<br> to_date('30-11-2005','DD-MM-YYYY'));<br>end;--命名符<br><br>begin<br>  DefaultTest(7);--定位符<br>end;<br><br><br><br><br>--9.1.3 call语句<br>call DefaultTest(10);<br>call DefaultTest();<br><br>begin<br> --call DefaultTest();<br> execute immediate 'call DefaultTest()';<br>end;<br><br><br><br>drop procedure DefaultTest;<br><br><br>------------------------------------<br>create or replace function CallFunc(p1 in varchar2)<br>  return varchar2 as<br>begin<br>  dbms_output.put_line('callfunc called with '||p1);<br>  return p1;<br>end;<br><br><br>declare <br> v_Result varchar2(50);<br>begin<br>  execute immediate <br>    'call CallFunc(''hello from pl/sql'')into :v_Result '<br>    using out v_Result;<br>end;<br><br>drop function CallFunc;<br><br><br>---------------------------------------<br>create or replace package packA as<br>  procedure xxxx1(p_var1 in number);<br>end packA;<br>create or replace package body packA as<br>  procedure xxxx2(p_var1 in number) is<br>  begin<br>    dbms_output.put_line('xxxx2 '||p_var1);<br>  end;--xxxx2必须在xxxx1之前，xxxx1才能调用到xxxx2<br>  <br>  procedure xxxx1(p_var1 in number) is<br>  begin<br>    dbms_output.put_line('xxxx1 '||p_var1);<br>    dbms_output.put_line('xxxx1 call xxxx2');<br>    xxxx2(2);<br>  end;<br>  <br>end packA;<br><br><br><br>begin<br>packA.xxxx1(1);<br>--packA.xxxx2(1);--not visible from outside <br>end;<br><br>drop package packA;<br><br><br><br>-------------------------------------------------------------------<br>--chapter 10<br>--10.1.1<br>create or replace procedure Simple as <br> v_Counter number;<br>begin<br> v_Counter:=7;<br>end Simple;<br><br>select *<br>from user_objects<br>where object_name='SIMPLE'--存储在数据字典中的都是大写<br><br>select * <br>from user_source--源代码<br>where name='SIMPLE' order by line<br><br><br>create or replace procedure Simple as <br> v_Counter number;<br>begin<br> v_Counter:=7--;<br>end Simple;<br><br><br>select * <br>from user_errors <br>where name='SIMPLE'<br><br>begin<br>  Simple;<br>end;<br>drop procedure Simple;<br><br>--------------------------------<br>--10.1.2<br>create or replace procedure Simple as <br> <br> v_Counter number;<br> <br> function formatName(p_FirstName in varchar2,p_LastName in<br> varchar2)--只能放在声明最后<br>   return varchar2 is<br> begin<br>   dbms_output.put_line(p_FirstName||' '||p_LastName);<br> end formatName;<br>begin<br> v_Counter:=7;<br>end Simple;<br><br><br>create or replace procedure Simple2 as<br>  procedure BBB;--预先声明<br>  procedure AAA is <br>  begin<br>    BBB;<br>  end AAA;<br>  <br>  procedure BBB is <br>  begin<br>    AAA;<br>  end BBB;<br>  <br>begin<br>  null;<br>end Simple2;<br><br><br><br><br><br>------------------------------------------------------------------------------------------<br>begin<br>dbms_shared_pool.sizes(1);<br>end;<br><br><br><br>-------------------------------------------------------------------------------------------<br>--charter 12<br>--绑定变量<br>declare<br> v_Type dictionary.type%type;<br> v_Name dictionary.valuename%type;<br> v_Sql varchar(200);<br>begin<br> v_Type:='Status';<br> v_Sql := 'select valuename  from dictionary where rownum=1 and<br> type=:type and languagecode=''cn''';<br> execute immediate  v_Sql into v_Name using v_Type;<br> dbms_output.put_line(v_Name);<br> <br> <br> <br>end;<br><br><br><br>--集体绑定<br>declare <br>  type t_Table is table of varchar(20) index by binary_integer;<br>  v_Table t_Table;<br>begin<br>  for v_Count in 1..100 loop<br>    v_Table(v_Count):=to_char(v_Count);<br>  end loop;<br>  <br>  forall v_Count in 1..100<br>    insert into jjl values(v_Table(v_Count));<br>  dbms_output.put_line(sql%rowcount);<br>  commit;<br>  forall v_Count in 1..100<br>    delete jjl where a1=(v_Table(v_Count));<br>  dbms_output.put_line(sql%rowcount);<br>  commit;<br>end;<br><br>select * from jjl<br><br>--bulk collect<br><br>declare<br>  type t_Table is table of jjl.a1%type index by binary_integer;<br>  v_Table t_Table;<br>  v_var jjl.a1%type;<br>begin<br>  select a1 <br>    bulk collect into v_Table<br>    from jjl;<br>  --for v_count in 1..v_Table.count loop<br>  dbms_output.put_line(v_Table.count);<br> -- end loop;<br>  <br>  for v_count in 1..6 loop<br>   dbms_output.put_line(substr(v_Table(v_count)));<br>  end loop;<br>end;<br><br><br><br><br><br><br><br><br><br><br><br><br>declare <br>v_xxx number(10):=1;<br>begin<br> dbms_output.put_line('v_xxx is '||v_xxx);<br> v_xxx:=null;<br> dbms_output.put_line('v_xxx is '||to_char(v_xxx));<br>end;<br><br><br><br>declare<br> type t_cur is ref cursor;<br> v_cur t_cur;<br> v_usr usr%rowtype;<br> v_sql varchar2(100):='select userid,username from usr';<br> v_userid usr.userid%type;<br> v_username usr.username%type;<br> --'select userid,username from usr' 报错数量不一致<br>begin<br>  open v_cur for v_sql;<br>  loop<br>    fetch v_cur into v_userid,v_username;<br>    exit when v_cur%notfound;<br>    dbms_output.put_line(to_char(v_userid));<br>  end loop;<br>  close v_cur;<br>  <br>end;<br><br><br>select instr('aaa','b') from dual<br>declare<br>  v_str varchar2(1000):='aaa,bbb,ccc,ddd,eee,fff';<br>  v_tmpstr varchar2(1000);<br>  v_dest varchar2(1000);<br>begin<br>  v_str := ''''||v_str||'''';<br>  v_str := replace(v_str,',',''',''');<br>  dbms_output.put_line(v_str);<br>end;<br><br><br><br>create or replace function xjp3addquote(p_str in varchar2) return<br> varchar2 as<br>  v_desc varchar2(2000);<br>begin<br>  v_desc := ''''||p_str||'''';<br>  v_desc := replace(v_desc,',',''',''');<br>  return v_desc;<br>end;<br><br><br>declare<br> v_aa number(3):=2;<br> v_bb number(3):=0;<br> v_cc number(4,2); <br>begin<br>  v_cc := v_aa/v_bb;<br><br>  --dbms_output.put_line(substr(sqlerrm,1,128));<br>end;</tt></tt></pre><img src ="http://www.blogjava.net/shypwang/aggbug/138788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shypwang/" target="_blank">妖人</a> 2007-08-23 12:31 <a href="http://www.blogjava.net/shypwang/articles/138788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>临时表temporary table</title><link>http://www.blogjava.net/shypwang/articles/138781.html</link><dc:creator>妖人</dc:creator><author>妖人</author><pubDate>Thu, 23 Aug 2007 04:15:00 GMT</pubDate><guid>http://www.blogjava.net/shypwang/articles/138781.html</guid><wfw:comment>http://www.blogjava.net/shypwang/comments/138781.html</wfw:comment><comments>http://www.blogjava.net/shypwang/articles/138781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shypwang/comments/commentRss/138781.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shypwang/services/trackbacks/138781.html</trackback:ping><description><![CDATA[<div class="storyTitle">
临时表temporary table
</div>
<div class="noDisplay">
===========================================================
</div>
<div class="storyInfo">
作者: xsb(http://xsb.itpub.net)<br>
发表于:2005.08.19 09:22<br>
分类:
Oracle
<br>
出处：http://xsb.itpub.net/post/419/38485<br>
--------------------------------------------------------------- <br>
</div>
<div class="storytext">
a<br>8i以上版本。<br>
Oracle 的临时表与MSSQL的不同，临时表需要先创建，不建议在运行时使用DDL语句创建！<br>
临时表可以看作是一张普通的物理表，在其上可以建索引、建视图，建触发器等！但它的数据是会话隔离的。<br>
区别之处:<br>
l	向表中插入数据只在会话或事务期间存在<br>
l	表中的数据只对插入数据的会话是可见的<br>
l	可用ON COMMIT指导定数据是会话专用还是事务专用<br>
临时表的限定:<br>
l	临时表不能被分区<br>
l	不能指定约束<br>
l	不包括含嵌套表的列或VARRAY类型<br>
l	不能指定TABLESPACE, STORAGE_CLAUSE, LONGGING, NOLOGGING, MONITORING, LOB_INDEX_CLAUSE等<br>
l	不能指定SEGMENT_ATTRIBUTES_CLAUSE,NESTED_TABLE_COL_PROPERTIES或PARALLEL_CLAUSE<br>
l	分布事务不支持临时表<br>
<br>
临时表的创建：<br>
create global temporary tablename(column list)&nbsp;<br>
on commit preserve rows; --提交保留数据  会话临时表&nbsp;<br>
on commit delete rows; --提交删除数据  事务临时表&nbsp;<br>
临时表是相对于会话的，别的会话看不到该会话的数据。<br>
oracle的临时表和sql server不一样，在使用完成以后，oracle临时表中的纪录可以被定义为自动删除（分session方式和transaction方式），而表结构不会被自动删除；sql server中的临时表在使用后会被完全删除。<br>
所以，如果是常用的临时表，你不妨一开始就建好表。<br>
在使用的时候，不同对话之间的纪录互相不干扰，所以不会给使用带来任何问题。<br>
<br>
对偶尔使用的临时表，也可以在过程中用动态SQL来建立（但不建议，DDL语句有较大的开销！）：<br>
CREATE OR REPLACE PROCEDURE myProc(...)  AUTHID current_user IS<br>
...<br>
BEGIN<br>
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY ....';<br>
...<br>
END;<br>
建议：<br>
不得已的情况下（比较复杂的数据处理）才使用临时表，否则尽可能使用子查询代替或使用游标。
</div><img src ="http://www.blogjava.net/shypwang/aggbug/138781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shypwang/" target="_blank">妖人</a> 2007-08-23 12:15 <a href="http://www.blogjava.net/shypwang/articles/138781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle临时表</title><link>http://www.blogjava.net/shypwang/articles/138773.html</link><dc:creator>妖人</dc:creator><author>妖人</author><pubDate>Thu, 23 Aug 2007 03:53:00 GMT</pubDate><guid>http://www.blogjava.net/shypwang/articles/138773.html</guid><wfw:comment>http://www.blogjava.net/shypwang/comments/138773.html</wfw:comment><comments>http://www.blogjava.net/shypwang/articles/138773.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shypwang/comments/commentRss/138773.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shypwang/services/trackbacks/138773.html</trackback:ping><description><![CDATA[<div class="postTitle">
<a  href="http://www.blogjava.net/pdw2009/archive/2007/06/20/125383.html" id="viewpost1_TitleUrl" class="postTitle2">oracle临时表</a>
</div>
在Oracle8i或以上版本中，可以创建以下两种临时表： <br>1。会话特有的临时表 <br>&nbsp;&nbsp;&nbsp;&nbsp;CREATE GLOBAL TEMPORARY &lt;TABLE_NAME&gt; (&lt;column specification&gt;) <br>&nbsp;&nbsp;&nbsp;&nbsp;ON COMMIT PRESERVE ROWS； <br>&nbsp;&nbsp;<br>2。事务特有的临时表 <br>&nbsp;&nbsp;&nbsp;&nbsp;CREATE GLOBAL TEMPORARY &lt;TABLE_NAME&gt; (&lt;column specification&gt;) <br>&nbsp;&nbsp;&nbsp;&nbsp;ON COMMIT DELETE ROWS； <br>&nbsp;&nbsp; CREATE GLOBAL TEMPORARY TABLE MyTempTable <br>所建的临时表虽然是存在的，但是你试一下insert 一条记录然后用别的连接登上去select，记录是空的，明白了吧，我把下面两句话再贴一下： <br>--ON COMMIT DELETE ROWS 说明临时表是事务指定，每次提交后ORACLE将截断表（删除全部行） <br>--ON COMMIT PRESERVE ROWS 说明临时表是会话指定，当中断会话时ORACLE将截断表。 <br>冲突的问题更本不用考虑. <br>&nbsp;&nbsp;<br>临时表只是保存当前会话(session)用到的数据，数据只在事务或会话期间存在。 <br>&nbsp;&nbsp;<br>通过CREATE GLOBAL TEMPORARY TABLE命令创建一个临时表，对于事务类型的临时表， <br>数据只是在事务期间存在，对于会话类型的临时表，数据在会话期间存在。 <br>&nbsp;&nbsp;<br>会话的数据对于当前会话私有。每个会话只能看到并修改自己的数据。DML锁不会加到 <br>临时表的数据上。下面的语句控制行的存在性。 <br>&nbsp;&nbsp; <br>● ON COMMIT DELETE ROWS 表名行只是在事务期间可见 <br>● ON COMMIT PRESERVE ROWS 表名行在整个会话期间可见 <br>&nbsp;&nbsp;<br>可以对临时表创建索引，视图，出发器，可以用export和import工具导入导出表的 <br>定义，但是不能导出数据。表的定义对所有的会话可见。<br><br><br>Temporary Tables临时表<br>1简介<br>&nbsp;&nbsp; ORACLE数据库除了可以保存永久表外，还可以建立临时表temporary tables。这些临时表用来保存一个会话SESSION的数据，<br>&nbsp;&nbsp; 或者保存在一个事务中需要的数据。当会话退出或者用户提交commit和回滚rollback事务的时候，临时表的数据自动清空，<br>&nbsp;&nbsp; 但是临时表的结构以及元数据还存储在用户的数据字典中。<br>&nbsp;&nbsp; 临时表只在oracle8i以及以上产品中支持。<br>2详细介绍<br>&nbsp;&nbsp; Oracle临时表分为 会话级临时表 和 事务级临时表。<br>会话级临时表是指临时表中的数据只在会话生命周期之中存在，当用户退出会话结束的时候，Oracle自动清除临时表中数据。<br>事务级临时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束（commit or rollback），Oracle自动清除临时表中数据。<br>临时表中的数据只对当前Session有效，每个Session都有自己的临时数据，并且不能访问其它Session的临时表中的数据。因此，<br>临时表不需要DML锁.当一个会话结束(用户正常退出 用户不正常退出 ORACLE实例崩溃)或者一个事务结束的时候，Oracle对这个会话的<br>表执行 TRUNCATE 语句清空临时表数据.但不会清空其它会话临时表中的数据.<br>你可以索引临时表和在临时表基础上建立视图.同样,建立在临时表上的索引也是临时的,也是只对当前会话或者事务有效.&nbsp;&nbsp;<br>临时表可以拥有触发器.<br>3建立临时表<br>&nbsp;&nbsp; 临时表的定义对所有会话SESSION都是可见的,但是表中的数据只对当前的会话或者事务有效. <br>&nbsp;&nbsp; 建立方法:<br>1) ON COMMIT DELETE ROWS 定义了建立事务级临时表的方法.<br>CREATE GLOBAL TEMPORARY TABLE admin_work_area<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(startdate DATE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enddate DATE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class CHAR(20))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ON COMMIT DELETE ROWS;<br>EXAMPLE:<br>SQL&gt; CREATE GLOBAL TEMPORARY TABLE admin_work_area<br>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(startdate DATE,<br>&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enddate DATE,<br>&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class CHAR(20))<br>&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ON COMMIT DELETE ROWS;<br>SQL&gt; create table permernate( a number);<br>SQL&gt; insert into admin_work_area values(sysdate,sysdate,'temperary table');<br>SQL&gt; insert into permernate values(1);<br>SQL&gt; commit;<br>SQL&gt; select * from admin_work_area;<br>SQL&gt; select&nbsp;&nbsp;* from permernate;<br>A<br>1<br>2)ON COMMIT PRESERVE ROWS 定义了创建会话级临时表的方法.<br>CREATE GLOBAL TEMPORARY TABLE admin_work_area<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(startdate DATE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enddate DATE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class CHAR(20))<br>&nbsp;&nbsp;&nbsp;&nbsp; ON COMMIT PRESERVE ROWS;<br>EXAMPLE:<br><br>会话1:<br>SQL&gt; drop table admin_work_area;<br>SQL&gt; CREATE GLOBAL TEMPORARY TABLE admin_work_area<br>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(startdate DATE,<br>&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enddate DATE,<br>&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class CHAR(20))<br>&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ON COMMIT PRESERVE ROWS;<br>SQL&gt; insert into permernate values(2);<br>SQL&gt; insert into admin_work_area values(sysdate,sysdate,'session temperary');<br>SQL&gt; commit;<br>SQL&gt; select * from permernate;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A<br>----------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br><br>SQL&gt; select * from admin_work_area;<br><br>STARTDATE&nbsp;&nbsp;ENDDATE&nbsp;&nbsp;&nbsp;&nbsp;CLASS<br>---------- ---------- --------------------<br>17-1?? -03 17-1?? -03 session temperary<br><br>会话2:<br><br>SQL&gt; select * from permernate;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A<br>----------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br><br>SQL&gt; select * from admin_work_area;<br><br>未选择行.<br><br>会话2看不见会话1中临时表的数据.<img src ="http://www.blogjava.net/shypwang/aggbug/138773.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shypwang/" target="_blank">妖人</a> 2007-08-23 11:53 <a href="http://www.blogjava.net/shypwang/articles/138773.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>