﻿<?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-把永恒在一刹那间收藏-文章分类-oracle</title><link>http://www.blogjava.net/gm_jing/category/13517.html</link><description>生活之点点滴滴</description><language>zh-cn</language><lastBuildDate>Wed, 27 Oct 2010 11:40:58 GMT</lastBuildDate><pubDate>Wed, 27 Oct 2010 11:40:58 GMT</pubDate><ttl>60</ttl><item><title>oracle 性能优化建议小结</title><link>http://www.blogjava.net/gm_jing/articles/336288.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 27 Oct 2010 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/336288.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/336288.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/336288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/336288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/336288.html</trackback:ping><description><![CDATA[<div id="art_demo">平时关注Oracle数据库的网友都知道，Oracle性能优化保证了Oracle数据库的健壮性。下面就此提出需要注意的两个原则。</div>
<p><strong>原则一：注意WHERE子句中的连接顺序： <br />
</strong>ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. <br />
尤其是&#8220;主键ID=？&#8221;这样的条件。 </p>
<p><strong>原则二： SELECT子句中避免使用 &#8216; * &#8216;： <br />
</strong>ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间 。 </p>
<p>简单地讲，语句执行的时间越短越好（尤其对于系统的终端用户来说）。而对于查询语句，由于全表扫描读取的数据多，尤其是对于大型表不仅查询速度慢，而且对磁盘IO造成大的压力，通常都要避免，而避免的方式通常是使用索引Index。 </p>
<p><strong>使用索引的优势与代价。</strong><br />
<strong>优势：</strong><br />
1）索引是表的一个概念部
分,用来提高检索数据的效率，ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快.
当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率.<br />
2） 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率.<br />
<strong>代价：</strong>
虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,
索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O .
因为索引需要额外的存储空间和处理,那些不必要的索引反而会 使查询反应时间变慢.。而且表越大，影响越严重。 </p>
<p>使用索引需要注意的地方：</p>
<p><strong>1、避免在索引列上使用NOT ，</strong>　 <br />
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE&#8221;遇到&#8221;NOT,他就会停止使用索引转而执行全表扫描.</p>
<p><strong>2、避免在索引列上使用计算． <br />
</strong>WHERE子句中，如果索引列是函数的一部分．优化器将不使用索引而使用全表扫描． 举例: <br />
</p>
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code26217"><br />
低效:SELECT &#8230; FROM DEPT WHERE SAL * 12 &gt; 25000; <br />
高效:SELECT &#8230; FROM DEPT WHERE SAL &gt; 25000/12;<br />
</div>
<br />
<strong>3、避免在索引列上使用IS NULL和IS NOT NULL</strong> <br />
避
免在索引中使用任何可以为空的列，ORACLE性能上将无法使用该索引．对于单列索引，如果列包含空值，索引中将不存在此记录.
对于复合索引，如果每个列都为空，索引中同样不存在此记录.　如果至少有一个列不为空，则记录存在于索引中．举例:
如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) ,
ORACLE将不接受下一条具有相同A,B值（123,null）的记录(插入).
然而如果所有的索引列都为空，ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空!
因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引. <br />
<br />
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code17931"> <br />
低效:(索引失效) SELECT &#8230; FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL; <br />
高效:(索引有效) SELECT &#8230; FROM DEPARTMENT WHERE DEPT_CODE &gt;=0; <br />
</div>
<br />
<br />
<strong>4、注意通配符%的影响 <br />
</strong>使用通配符的情况下Oracle可能会停用该索引。如 : <br />
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code95905"> <br />
SELECT&#8230;FROM DEPARTMENT WHERE DEPT_CODE like &#8216;%123456%'（无效）。 <br />
SELECT&#8230;FROM DEPARTMENT WHERE DEPT_CODE = &#8216;123456'（有效） <br />
</div>
<br />
<strong>5、避免改变索引列的类型.:</strong> <br />
当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. <br />
假
设 EMPNO是一个数值类型的索引列. SELECT &#8230; FROM EMP WHERE EMPNO = &#8216;123'
实际上,经过ORACLE类型转换, 语句转化为: SELECT &#8230; FROM EMP WHERE EMPNO =
TO_NUMBER(&#8216;123') 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变.
现在,假设EMP_TYPE是一个字符类型的索引列. SELECT &#8230; FROM EMP WHERE EMP_TYPE = 123
这个语句被ORACLE转换为: SELECT &#8230; FROM EMP WHERETO_NUMBER(EMP_TYPE)=123
因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来.
注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型 <br />
<br />
<strong>6、索引的一些&#8220;脾气&#8221;</strong> <br />
a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高. <br />
b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍! <br />
<br />
<strong>除了使用索引，我们还有其他能减少资源消耗的方法：</strong><br />
<br />
<strong>1、用EXISTS替换DISTINCT：</strong> <br />
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. <br />
例子: <br />
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code35425"> <br />
(低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E <br />
WHERE D.DEPT_NO = E.DEPT_NO <br />
And E.sex =man <br />
(高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT D <br />
WHERE EXISTS <br />
( SELECT &#8216;X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO <br />
And E.sex =man <br />
); <br />
</div>
<br />
<strong>2、用(UNION)UNION ALL替换OR (适用于索引列)</strong> <br />
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. <br />
注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. <br />
如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面. <br />
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code16863"> <br />
高效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 UNION ALL <br />
SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = &#8220;MELBOURNE&#8221; <br />
低效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = &#8220;MELBOURNE&#8221; <br />
</div>
<br />
<strong>3、用UNION-ALL 替换UNION ( 如果有可能的话)：</strong> <br />
当
SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION
ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是，UNION ALL 将重复输出两个结果集合中相同记录.
因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION
将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是相当重要的. <br />
<strong>4、Order By语句加在索引列，最好是主键PK上。</strong> <br />
<div class="codetitle"><span style="cursor: pointer;"><u>复制代码</u></span> 代码如下:</div>
<div class="codebody" id="code99109"> <br />
SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE（低效） <br />
SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_CODE （高效） <br />
</div>
<br />
<strong>5、避免使用耗费资源的操作:</strong> <br />
带
有DISTINCT,UNION,MINUS,INTERSECT的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能.
DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS ,
INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS,
INTERSECT也是可以考虑的, 毕竟它们的可读性很强 <br />
<br />
<strong>6、使用Where替代Having（如果可以的话） <br />
</strong>优化GROUP BY: <br />
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. <br />
<br />
<div class="codebody" id="code25812"> <br />
低效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP GROUP JOB HAVING JOB = &#8216;PRESIDENT'AND AVG(SAL)&gt;XXX <br />
高效: <br />
SELECT JOB , AVG(SAL) <br />
FROM EMP <br />
WHERE JOB = &#8216;PRESIDENT' <br />
OR JOB = &#8216;MANAGER' GROUP JOB Having AND AVG(SAL)&gt;XXX <br />
</div>
<br />
<strong>7、通常来说，如果语句能够避免子查询的 使用，就尽量不用子查询。</strong>因为子查询的开销是相当昂贵的。具体的例子在后面的案例&#8220;一条SQL的优化过程&#8221;中。
<img src ="http://www.blogjava.net/gm_jing/aggbug/336288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-10-27 16:09 <a href="http://www.blogjava.net/gm_jing/articles/336288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>expert one-to-one oracle学习(第一章)</title><link>http://www.blogjava.net/gm_jing/articles/320511.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 10 May 2010 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/320511.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/320511.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/320511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/320511.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/320511.html</trackback:ping><description><![CDATA[<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 11" />
<meta name="Originator" content="Microsoft Word 11" />
<link rel="File-List" href="file:///C:%5CDOCUME%7E1%5Cu121871%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml" /><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 pt</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles deflockedstate="false" latentstylecount="156">
</w:LatentStyles>
</xml><![endif]--><style>
<!-- /* Font Definitions */
@font-face
{font-family:"MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-alt:"ＭＳ 明朝";
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:BaskervilleBE-Regular;
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:"Times New Roman";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:"\@MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:ZapfDingbats;
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:黑体;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:1 135135232 16 0 262144 0;}
@font-face
{font-family:BaskervilleBE-Italic;
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-alt:"Times New Roman";
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:"\@ZapfDingbats";
panose-1:0 0 0 0 0 0 0 0 0 0;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-format:other;
mso-font-pitch:auto;
mso-font-signature:1 135135232 16 0 262144 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{mso-list-id:443577112;
mso-list-type:hybrid;
mso-list-template-ids:1615490908 2120265834 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
{mso-level-text:%1、;
mso-level-tab-stop:18.0pt;
mso-level-number-position:left;
margin-left:18.0pt;
text-indent:-18.0pt;}
@list l1
{mso-list-id:1248687835;
mso-list-type:hybrid;
mso-list-template-ids:-2047193462 428628834 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l1:level1
{mso-level-number-format:japanese-counting;
mso-level-text:第%1章、;
mso-level-tab-stop:54.0pt;
mso-level-number-position:left;
margin-left:54.0pt;
text-indent:-54.0pt;}
@list l2
{mso-list-id:1508135424;
mso-list-type:hybrid;
mso-list-template-ids:-944592998 -358962658 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l2:level1
{mso-level-text:%1、;
mso-level-tab-stop:18.0pt;
mso-level-number-position:left;
margin-left:18.0pt;
text-indent:-18.0pt;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]-->
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 54pt; text-indent: -54pt;"><!--[if !supportLists]--><strong><span lang="EN-US"><span>第一章、<span style="font: 7pt &quot;Times New Roman&quot;;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span></strong><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">开发成功的</span></strong><strong><span style="font-size: 12pt;" lang="EN-US">Oracle</span></strong><strong><span style="font-size: 12pt; font-family: 宋体;">应用程序</span></strong><strong><span lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: ZapfDingbats;">❑</span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US"> You should do it in a single SQL
statement if at all possible.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: ZapfDingbats;">❑</span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US"> If you cannot do it in a single
SQL Statement, then do it in PL/SQL.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: ZapfDingbats;">❑</span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US"> If you cannot do it in PL/SQL, try
a Java Stored Procedure.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: ZapfDingbats;">❑</span><span style="font-family: BaskervilleBE-Regular;"> <span lang="EN-US">If you cannot do it in Java, do it in a
C external procedure.<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: ZapfDingbats;">❑</span><span style="font-family: BaskervilleBE-Regular;"> <span lang="EN-US">If you cannot do it in a C external
routine, you might want to seriously think about why it is you need to do it...<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;这段表明我们操作一个过程， 简单来说，优先选择SQL<br />
</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">SQL中一些注意</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span style="font-size: 12pt;" lang="EN-US"><span>1、</span></span><!--[endif]--><span style="font-size: 12pt; font-family: 宋体;">不要在</span><span style="font-size: 12pt;" lang="EN-US">MTS</span><span style="font-size: 12pt; font-family: 宋体;">下运行长事务</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span style="font-size: 12pt;" lang="EN-US"><span>2、</span></span><!--[endif]--><span style="font-size: 12pt; font-family: 宋体;">使用绑定变量</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">理解并行控制</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span style="font-size: 12pt;" lang="EN-US"><span>1、</span></span><!--[endif]--><span style="font-size: 12pt; font-family: 宋体;">锁</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: &quot;MS Mincho&quot;;">❑</span><span style="font-family: ZapfDingbats;"> </span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">Oracle locks
data at the row level on modification only. There is no lock escalation to a
block<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">or table
level, ever.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: &quot;MS Mincho&quot;;">❑</span><span style="font-family: ZapfDingbats;"> </span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">Oracle never
locks data just to read it. There are no locks placed on rows of data by simple<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">reads.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: &quot;MS Mincho&quot;;">❑</span><span style="font-family: ZapfDingbats;"> </span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">A writer of
data does not block a reader of data. Let me repeat &#8211; </span><em><span style="font-family: BaskervilleBE-Italic;" lang="EN-US">reads </span></em><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">are not
blocked by<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><em><span style="font-family: BaskervilleBE-Italic;" lang="EN-US">writes</span></em><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">. This is fundamentally different from almost every other
database, where reads are<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">blocked by
writes.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: &quot;MS Mincho&quot;;">❑</span><span style="font-family: ZapfDingbats;"> </span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">A writer of
data is blocked only when another writer of data has already locked the row it
was<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">going after. A
reader of data never blocks a writer of data.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: ZapfDingbats;">所以实际应用时候，注意改变锁的级别</span><span style="font-family: BaskervilleBE-Regular;" lang="EN-US">!!!<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: BaskervilleBE-Regular;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span style="font-size: 12pt;" lang="EN-US"><span>2、</span></span><!--[endif]--><span style="font-size: 12pt; font-family: 宋体;">多版本</span><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">主要针对写操作时候，对读操作不阻塞</span></p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal">具体来说： (R-read&nbsp; W-write)<br />
</p>
<p class="MsoNormal">R/R&nbsp;&nbsp;&nbsp; 　　 不上锁，但是如果两个线程先读再修改，则需要加SS锁(for update)<br />
</p>
<p class="MsoNormal">R/W&nbsp; W/R&nbsp;&nbsp; 多版本控制，不阻塞读</p>
<p class="MsoNormal">W/W&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用SX锁，阻塞任何ＤＭＬ操作<br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px 宋体; text-transform: none; color: #42495b; text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2;"><font style="background-color: #ffffff;"><span style="font-weight: bold;">DML锁分类表</span><br />
</font>
<table bgcolor="#ffffff" border="1" bordercolor="#666666" cellpadding="1" cellspacing="0" width="456" height="194">
    <tbody>
        <tr>
            <td colspan="4"><span><font style="background-color: #ffffff;">表1 Oracle的TM锁类型</font></span></td>
        </tr>
        <tr>
            <td width="40"><span><font style="background-color: #ffffff;">锁模式</font></span></td>
            <td width="84"><span><font style="background-color: #ffffff;">锁描述</font></span></td>
            <td width="101"><span><font style="background-color: #ffffff;">解释</font></span></td>
            <td width="213"><span><font style="background-color: #ffffff;">SQL操作</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">0</font></span></td>
            <td><span><font style="background-color: #ffffff;">none</font></span></td>
            <td> <br />
            </td>
            <td> <br />
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">1</font></span></td>
            <td><span><font style="background-color: #ffffff;">NULL</font></span></td>
            <td><span><font style="background-color: #ffffff;">空</font></span></td>
            <td><span><font style="background-color: #ffffff;">Select</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">2</font></span></td>
            <td><span><font style="background-color: #ffffff;">SS(Row-S)</font></span></td>
            <td><span><font style="background-color: #ffffff;">行级共享锁，其他对象只能查询这些数据行</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Select
            for update、Lock for update、Lock row share</font></p>
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">3</font></span></td>
            <td><span><font style="background-color: #ffffff;">SX(Row-X)</font></span></td>
            <td><span><font style="background-color: #ffffff;">行级排它锁，在提交前不允许做DML操作</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Insert、
            Update、Delete、Lock row share</font></p>
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">4</font></span></td>
            <td><span><font style="background-color: #ffffff;">S(Share)</font></span></td>
            <td><span><font style="background-color: #ffffff;">共享锁</font></span></td>
            <td><span><font style="background-color: #ffffff;">Create index、Lock share</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">5</font></span></td>
            <td><span><font style="background-color: #ffffff;">SSX(S/Row-X)</font></span></td>
            <td><span><font style="background-color: #ffffff;">共享行级排它锁</font></span></td>
            <td><span><font style="background-color: #ffffff;">Lock share row exclusive</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">6</font></span></td>
            <td><span><font style="background-color: #ffffff;">X(Exclusive)</font></span></td>
            <td><span><font style="background-color: #ffffff;">排它锁</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Alter
            table、Drop able、Drop index、Truncate table 、Lock exclusive</font></p>
            </td>
        </tr>
    </tbody>
</table>
</span><br />
<span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/320511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-05-10 17:33 <a href="http://www.blogjava.net/gm_jing/articles/320511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle 锁机制</title><link>http://www.blogjava.net/gm_jing/articles/320479.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 10 May 2010 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/320479.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/320479.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/320479.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/320479.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/320479.html</trackback:ping><description><![CDATA[<div id="blog_text" class="cnt"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px 宋体; text-transform: none; color: #42495b; text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2;">
<p style="text-indent: 2em;"><font style="background-color: #ffffff;">数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时，在数据库中就会产生多个事务同时存取同一数据的情况。若对并发
操作不加控制就可能会读取和存储不正确的数据，破坏数据库的一致性。 <br />
<br />
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前，先向系统发出请求，对其加锁。加锁后事务就对该数据对象有了一定的控
制，在该事务释放锁之前，其他的事务不能对此数据对象进行更新操作。 <br />
<br />
在数据库中有两种基本的锁类型：排它锁（Exclusive Locks，即X锁）和共享锁（Share
Locks，即S锁）。当数据对象被加上排它锁时，其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取，但不能修改。数据库利用这两
种基本的锁类型来对数据库的事务进行并发控制。 <br />
<br />
<br />
<br />
<span>Oracle</span>数据库的锁类型 <br />
<br />
根据保护的对象不同，<span>Oracle</span>数据库锁可以分为以下几大类：DML锁（data
locks，数据锁），用于保护数据的完整性；DDL锁（dictionary
locks，字典锁），用于保护数据库对象的结构，如表、索引等的结构定义；内部锁和闩（internal locks and latches），保护
数据库的内部结构。 <br />
<br />
DML锁的目的在于保证并发情况下的数据完整性，。在<span>Oracle</span>数据库中，DML锁主要包括<span>TM锁</span>和
TX锁，其中<span>TM锁</span>称为表级锁，TX锁称为事务锁或行级锁。 <br />
<br />
当<span>Oracle</span> 执行DML语句时，系统自动在所要操作的表上申请TM类型的锁。当<span>TM锁</span>获得后，
系统再自动申请TX类型的锁，并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志，而只需检查<span>TM
锁</span>模式的相容性即可，大大提高了系统的效率。<span>TM锁</span>包括了SS、SX、S、X
等多种模式，在数据库中用0－6来表示。不同的SQL操作产生不同类型的<span>TM锁</span>。 <br />
<br />
在数据行上只有X锁（排他锁）。在 <span>Oracle</span>数据库中，当一个事务首次发起一个DML语句时就获得一个TX锁，该锁保持到
事务被提交或回滚。当两个或多个会话在表的同一条记录上执行
DML语句时，第一个会话在该条记录上加锁，其他的会话处于等待状态。当第一个会话提交后，TX锁被释放，其他会话才可以加锁。 <br />
<br />
当<span>Oracle</span>数据库发生TX锁等待时，如果不及时处理常常会引起<span>Oracle</span>数据库挂起，或导致
死锁的发生，产生ORA-60的错误。这些现象都会对实际应用产生极大的危害，如长时间未响应，大量事务失败等。 <br />
<br />
悲观封锁和乐观封锁 <br />
一、悲观封锁 <br />
锁在用户修改之前就发挥作用： <br />
Select ..for update（nowait) <br />
Select * from tab1 for update <br />
用户发出这条命令之后，<span>oracle</span>将会对返回集中的数据建立行级封锁，以防止其他用户的修改。 <br />
如果此时其他用户对上面返回结果集的数据进行dml或ddl操作都会返回一个错误信息或发生阻塞。 <br />
1：对返回结果集进行update或delete操作会发生阻塞。 <br />
2：对该表进行ddl操作将会报：Ora-00054:resource busy and acquire with nowait
specified. <br />
<br />
原因分析 <br />
此时<span>Oracle</span>已经对返回的结果集上加了排它的行级锁，所有其他对这些数据进行的修改或删除操作都必须等待这个锁的释放，产
生的外在现象就是其他的操作将发生阻塞，这个这个操作commit或rollback. <br />
同样这个查询的事务将会对该表加表级锁，不允许对该表的任何ddl操作，否则将会报出ora-00054错误：:resource busy and
acquire with nowait specified. <br />
<br />
二、乐观封锁 <br />
乐观的认为数据在select出来到update进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定，是存
在一种可能被其他用户更改的可能。因此<span>Oracle</span>仍然建议是用悲观封锁，因为这样会更安全。 <br />
<br />
<br />
阻塞 <br />
<br />
定义： <br />
当一个会话保持另一个会话正在请求的资源上的锁定时，就会发生阻塞。被阻塞的会话将一直挂起，直到持有锁的会话放弃锁定的资源为止。4个常见的dml语句
会产生阻塞 <br />
INSERT <br />
UPDATE <br />
DELETE <br />
SELECT&#8230;FOR UPDATE <br />
<br />
<br />
INSERT <br />
<br />
Insert发生阻塞的唯一情况就是用户拥有一个建有主键约束的表。当2个的会话同时试图向表中插入相同的数据时，其中的一个会话将被阻塞，直到另外一个
会话提交或会滚。一个会话提交时，另一个会话将收到主键重复的错误。回滚时，被阻塞的会话将继续执行。 <br />
<br />
UPDATE 和DELETE当执行Update和delete操作的数据行已经被另外的会话锁定时，将会发生阻塞，直到另一个会话提交或会滚。 <br />
<br />
Select &#8230;for update <br />
<br />
当一个用户发出select..for
update的错作准备对返回的结果集进行修改时，如果结果集已经被另一个会话锁定，就是发生阻塞。需要等另一个会话结束之后才可继续执行。可以通过发出
select&#8230; for update
nowait的语句来避免发生阻塞，如果资源已经被另一个会话锁定，则会返回以下错误：Ora-00054:resource busy and
acquire with nowait specified. <br />
<br />
<br />
<br />
死锁-deadlock <br />
<br />
定义:当两个用户希望持有对方的资源时就会发生死锁. <br />
即两个用户互相等待对方释放资源时,<span>oracle</span>认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续
执行,牺牲的用户的事务将回滚. <br />
例子： <br />
1：用户1对A表进行Update，没有提交。 <br />
2：用户2对B表进行Update，没有提交。 <br />
此时双反不存在资源共享的问题。 <br />
3：如果用户2此时对A表作update,则会发生阻塞，需要等到用户一的事物结束。 <br />
4：如果此时用户1又对B表作update，则产生死锁。此时<span>Oracle</span>会选择其中一个用户进行会滚，使另一个用户继续执行
操作。 <br />
起因: <br />
<span>Oracle</span>的死锁问题实际上很少见，如果发生，基本上都是不正确的程序设计造成的，经过调整后，基本上都会避免死锁的发生。
<br />
<br />
<span style="font-weight: bold;">DML锁分类表</span><br style="font-weight: bold;" />
<br />
<br />
</font>
<table bgcolor="#ffffff" border="1" bordercolor="#666666" cellpadding="1" cellspacing="0" width="456" height="194">
    <tbody>
        <tr>
            <td colspan="4"><span><font style="background-color: #ffffff;">表1 Oracle的TM锁类型</font></span></td>
        </tr>
        <tr>
            <td width="40"><span><font style="background-color: #ffffff;">锁模式</font></span></td>
            <td width="84"><span><font style="background-color: #ffffff;">锁描述</font></span></td>
            <td width="101"><span><font style="background-color: #ffffff;">解释</font></span></td>
            <td width="213"><span><font style="background-color: #ffffff;">SQL操作</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">0</font></span></td>
            <td><span><font style="background-color: #ffffff;">none</font></span></td>
            <td> <br />
            </td>
            <td> <br />
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">1</font></span></td>
            <td><span><font style="background-color: #ffffff;">NULL</font></span></td>
            <td><span><font style="background-color: #ffffff;">空</font></span></td>
            <td><span><font style="background-color: #ffffff;">Select</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">2</font></span></td>
            <td><span><font style="background-color: #ffffff;">SS(Row-S)</font></span></td>
            <td><span><font style="background-color: #ffffff;">行级共享锁，其他对象只能查询这些数据行</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Select
            for update、Lock for update、Lock row share</font></p>
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">3</font></span></td>
            <td><span><font style="background-color: #ffffff;">SX(Row-X)</font></span></td>
            <td><span><font style="background-color: #ffffff;">行级排它锁，在提交前不允许做DML操作</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Insert、
            Update、Delete、Lock row share</font></p>
            </td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">4</font></span></td>
            <td><span><font style="background-color: #ffffff;">S(Share)</font></span></td>
            <td><span><font style="background-color: #ffffff;">共享锁</font></span></td>
            <td><span><font style="background-color: #ffffff;">Create index、Lock share</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">5</font></span></td>
            <td><span><font style="background-color: #ffffff;">SSX(S/Row-X)</font></span></td>
            <td><span><font style="background-color: #ffffff;">共享行级排它锁</font></span></td>
            <td><span><font style="background-color: #ffffff;">Lock share row exclusive</font></span></td>
        </tr>
        <tr>
            <td><span><font style="background-color: #ffffff;">6</font></span></td>
            <td><span><font style="background-color: #ffffff;">X(Exclusive)</font></span></td>
            <td><span><font style="background-color: #ffffff;">排它锁</font></span></td>
            <td>
            <p><font style="background-color: #ffffff;">Alter
            table、Drop able、Drop index、Truncate table 、Lock exclusive</font></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p style="text-indent: 2em;">
设立封锁机制主要是为了对并发操作进行控制，对干扰进行封锁，保证数据的一致性和准确性。Oracle数据库封锁方式有三种：共享封锁，独占封锁，共享更
新封锁 <br />
封锁类型<br />
Oracle　RDBMS的封锁类型可分为如下三类： <br />
<br />
１、内部级封锁 <br />
内部级封锁是用于保护ORACLE内部结构，由<nobr style="color: #6600ff; border-bottom: 1px dotted #6600ff; background-color: transparent; text-decoration: underline;" target="_blank">系统</nobr>内部实现，
用户不能访问，因此我们不必对此做过多的了解。 <br />
<br />
２、DDL级封锁（字典/语法分析封锁） <br />
DDL级封锁也是由ORACLE　RDBMS来控制，它用于保护数据字典和数据定义改变时的一致性和完整性。它是系统在对SQL定义语句作语法分析时自动
地加锁，无需用户干予。字典/语法分析封锁共分三类： <br />
（１）、字典操作锁：用于对字典操作时，锁住数据字典，此封锁是独占的，从而保护任何一个时刻仅能对一个字典操作。 <br />
（２）、字典定义锁：用于防止在进行字典操作时又进行语法分析，这样可以避免在查询字典的同时改动某个表的结构。 <br />
（３）、表定义锁：用于　一个SQL语句正当访问某个表时，防止字典中与该表有关的项目被修改。 <br />
<br />
３、DML级封锁 <br />
DML级封锁用于控制并发事务中的数据操纵，保证数据的一致性和完整性，其封锁对象可以是表或行。 <br />
对用户的数据操纵，Oracle可以自动为操纵的数据进行封锁，但如果有操纵授权，则为满足并发操纵的需要另外实施封锁。DML封锁可由一个用户进程以显
式的方式加锁，也可通过某些　　 SQL语句隐含方式实现。 <br />
DML锁有如下三种封锁方式： <br />
（1）、共享封锁方式（SHARE） <br />
（2）、独占封锁方式（EXCLUSIVE） <br />
（3）、共享更新封锁（SHARE UPDATE） <br />
<br />
其中SHARE，EXCLUSIVE用于表封锁，SHARE UPDATE用于行封锁。 <br />
1、共享方式的表封锁 <br />
共享方式的表封锁是对表中的所有数据进行封锁，该锁用于保护查询数据的一致性，防止其它用户对已封锁的表进行更更新。其它用户只能对该表再施加共享方式的
锁，而不能再对该表施加独占方式的封锁，共享更新锁可以再施加，但不允许持有共享更新封锁的进程做更新。共享该表的所有用户只能查询表中的数据，但不能更
新。共享方式的表封锁只能由用户用SQL语句来设置，基语句格式如下： <br />
[quote:04b72348bd]LOCK TABLE &lt;表名&gt;[,&lt;表名&gt;]... <br />
IN SHARE MODE [NOWAIT] <br />
[/quote:04b72348bd] <br />
执行该语句，对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT，若该封锁暂时不能施加成功，则返回并由用户决定是进行等待，还是先去执行
别的语句。 <br />
持有共享锁的事务，在出现如下之一的条件时，便<nobr style="color: #6600ff; border-bottom: 1px dotted #6600ff; background-color: transparent; text-decoration: underline;" target="_blank">释放</nobr>其共享锁：
<br />
A、执行COMMIT或ROLLBACK语句。 <br />
B、退出数据库（LOG　OFF）。 <br />
C、程序停止运行。 <br />
共享方式表封锁常用于一致性查询过程，即在查询数据期间表中的数据不发生改变。 <br />
<br />
2、独占方式表封锁 <br />
独占方式表封锁是用于封锁表中的所有数据，拥有该独占方式表封锁的用户，即可以查询该表，又可以更新该表，其它的用户不能再对该表施加任何封锁（包括共
享、独占或共享更新封锁）。其它用户虽然不能更新该表，但可以查询该表。 <br />
独占方式的表封锁可通过如下的SQL语句来显示地获得： <br />
LOCK TABLE &lt;表名&gt;[,&lt;表名&gt;].... <br />
IN EXCLUSIVE MODE [NOWAIT] <br />
独占方式的表封锁也可以在用户执行DML语句INSERT、UPDATE、DELETE时隐含获得。 <br />
拥有独占方式表封锁的事务，在出现如下条件之一时，便释放该封锁： <br />
（1）、执行COMMIT或ROLLBACK语句。 <br />
（2）、退出数据库（LOG OFF） <br />
（3）、程序停止运行。 <br />
独占方式封锁通常用于更新数据，当某个更新事务涉及多个表时，可减少发生死锁。 <br />
<br />
DML锁有如下三种封锁方式： <br />
（1）、共享封锁方式（SHARE） <br />
（2）、独占封锁方式（EXCLUSIVE） <br />
（3）、共享更新封锁（SHARE UPDATE） <br />
其中SHARE，EXCLUSIVE用于表封锁，SHARE UPDATE用于行封锁。 <br />
<br />
1、共享方式的表封锁 <br />
共享方式的表封锁是对表中的所有数据进行封锁，该锁用于保护查询数据的一致性，防止其它用户对已封锁的表进行更更新。其它用户只能对该表再施加共享方式的
锁，而不能再对该表施加独占方式的封锁，共享更新锁可以再施加，但不允许持有共享更新封锁的进程做更新。共享该表的所有用户只能查询表中的数据，但不能更
新。共享方式的表封锁只能由用户用SQL语句来设置，基语句格式如下： <br />
[quote:04b72348bd]LOCK TABLE &lt;表名&gt;[,&lt;表名&gt;]... <br />
IN SHARE MODE [NOWAIT] <br />
[/quote:04b72348bd] <br />
执行该语句，对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT，若该封锁暂时不能施加成功，则返回并由用户决定是进行等待，还是先去执行
别的语句。 <br />
持有共享锁的事务，在出现如下之一的条件时，便释放其共享锁： <br />
A、执行COMMIT或ROLLBACK语句。 <br />
B、退出数据库（LOG　OFF）。 <br />
C、程序停止运行。 <br />
共享方式表封锁常用于一致性查询过程，即在查询数据期间表中的数据不发生改变。 <br />
<br />
2、独占方式表封锁 <br />
独占方式表封锁是用于封锁表中的所有数据，拥有该独占方式表封锁的用户，即可以查询该表，又可以更新该表，其它的用户不能再对该表施加任何封锁（包括共
享、独占或共享更新封锁）。其它用户虽然不能更新该表，但可以查询该表。 <br />
独占方式的表封锁可通过如下的SQL语句来显示地获得： <br />
LOCK TABLE &lt;表名&gt;[,&lt;表名&gt;].... <br />
IN EXCLUSIVE MODE [NOWAIT] <br />
独占方式的表封锁也可以在用户执行DML语句INSERT、UPDATE、DELETE时隐含获得。 <br />
拥有独占方式表封锁的事务，在出现如下条件之一时，便释放该封锁： &lt;BR&gt;（1）、执行　　 COMMIT或ROLLBACK语句。
<br />
（2）、退出数据库（LOG OFF） <br />
（3）、程序停止运行。 <br />
独占方式封锁通常用于更新数据，当某个更新事务涉及多个表时，可减少发生死锁。 <br />
<br />
3、共享更新封锁方式 <br />
共享更新封锁是对一个表的一行或多行进行封锁，因而也称作行级封锁。表级封锁虽然保证了数据的一致性，但却减弱了操作数据的并行性。行级封锁确保在用户取
得被更新的行到该行进行更新这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。 <br />
可通过如下的两种方式来获得行级封锁： <br />
（1）、执行如下的SQL封锁语句，以显示的方式获得： <br />
LOCK TABLE &lt;表名&gt;[,&lt;表名&gt;].... <br />
IN SHARE UPDATE　MODE [NOWAIT] <br />
（2）、用如下的SELECT ...FOR UPDATE语句获得： <br />
SELECT &lt;列名&gt;[,&lt;列名&gt;]... <br />
FROM &lt;表名&gt; <br />
WHERE &lt;条件&gt; <br />
FOR UPDATE OF &lt;列名&gt;[,&lt;列名&gt;].....[NOWAIT] <br />
一旦用户对某个行施加了行级封锁，则该用户可以查询也可以更新被封锁的数据行，其它用户只能查询但不能更新被封锁的数据行．如果其它用户想更新该表中的数
据行，则也必须对该表施加行级锁．即使多个用户对一个表均使用了共享更新，但也不允许两个事务同时对一个表进行更新，真正对表进行更新时，是以独占方式封
锁表，一直到提交或复原该事务为止。行锁永远是独占方式锁。 <br />
当出现如下之一的条件，便释放共享更新锁： <br />
（１）、执行提交（COMMIT）语句； <br />
（２）、退出数据库（LOG　OFF） <br />
（３）、程序停止运行。 <br />
执行ROLLBACK操作不能释放行锁。 <br />
从上面讲述可见，ORACLE　RDBMS的加锁机制，解决了并发事务的相容与互斥问题。相容保证事务的并发性，互斥确保数据的一致性。不同用户锁的相容
与互斥关系由下图给出。 <br />
<br />
其中最后一行最后一列为其它用户提供在不同行上设置SHARE
UPDATE锁。但当用户１在某行上进行更新操作时，用户２只有等待用户１提交事务后，才能更新自己所封锁的行。 <br />
<br />
中最后一行最后一列为其它用户提供在不同行上设置SHARE
UPDATE锁。但当用户１在某行上进行更新操作时，用户２只有等待用户１提交事务后，才能更新自己所封锁的行。 <br />
死锁 <br />
<br />
封锁虽然能够有效的解决并发操作，但是任何<a href="http://www.csai.cn/incsearch/search.asp?key=%D7%CA%D4%B4" target="_blank">资源</a>的独占都会有死锁的危险。例如：有两个事务T1，T2，T1对数据A施加独占封锁，T2对数据B施加了独占
封锁。再假设T1要对数据B加锁，由于B已被T2独占封锁，因此T1置于等待状态，等待B被释放；现在若T2也要对A进行封锁，由于A已被T1独占封锁，
因此T2也被置于等待状态。这样就形成了两个事务相互等待的状态，而且永远不能结束，此种情况称为死锁。 <br />
在Oracle系统中能自动发现死锁，并选择代价最小的，即完成<nobr style="color: #6600ff; border-bottom: 1px dotted #6600ff; background-color: transparent; text-decoration: underline;" target="_blank">工作</nobr>量最少的事
务予以撤消，释放该事务所拥有的全部锁，记其它的事务继续工作下去。 <br />
从系统性能上考虑，应该尽可能减少资源竞争，增大吞吐量，因此用户在给并发操作加锁时，应注意以下几点： <br />
１、对于UPDATE和DELETE操作，应只封锁要做改动的行，在完成修改后立即提交。 <br />
２、当多个事务正利用共享更新的方式进行更新，则不要使用共享封锁，而应采用共享更新封锁，这样其它用户就能使用行级锁，以增加并行性。 <br />
３、尽可能将对一个表的操作的并发事务施加共享更新锁，从而可提高并行性。 <br />
４、在<nobr style="color: #6600ff; border-bottom: 1px dotted #6600ff; background-color: transparent; text-decoration: underline;" target="_blank">应用</nobr>负荷较高的期间，不宜对基础<a href="http://www.csai.cn/incsearch/search.asp?key=%CA%FD%BE%DD%BD%E1%B9%B9" target="_blank">数据结构</a>（表、索引、簇和视图）进行修改</p>
</span></div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/320479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-05-10 15:42 <a href="http://www.blogjava.net/gm_jing/articles/320479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle中user和schema的区别[转]</title><link>http://www.blogjava.net/gm_jing/articles/292543.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 25 Aug 2009 10:17:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/292543.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/292543.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/292543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/292543.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/292543.html</trackback:ping><description><![CDATA[<h4 class="beTitle" id="subjcns!723590D920FAF62B!536">&nbsp;</h4>
<div class="bvMsg" id="msgcns!723590D920FAF62B!536">
<div>
<p>user和schema的区别:<br />
说穿了其实user是控制权限的，而schema是个容器，非所有者要访问这个容器下的对象就需要在<br />
对象前面写上schema（owner）的名字，如果不想写而又没有创建synonym，此时可以通过<br />
alter session set current_schema=schema_name<br />
来改变当前session的schema从而在访问对象时省去schema（owner）；<br />
最终能否访问对象还是要看是否有访问这个对象的权限而和schema无关。
<p>--下面的话是puber <a href="http://www.itpub.net/viewpro.php?uid=13171581" target="_blank"><u><font color="#0000ff">OoNiceDream</font></u></a> 发上来的一段非常经典形象的比喻。
<p>user即oracle中的用户，和所有系统的中用户概念类似，用户所持有的是系统的权限及资源；<br />
而schema所涵盖的是各种对象，它包含了表、函数、包等等对象的&#8220;所在地&#8221;，并不包括对他们的权限控制。<br />
好比一个房子，里面放满了家具，对这些家具有支配权的是房子的主人（user），而不是房子（schema）。<br />
你可以也是一个房子的主人（user），拥有自己的房子（schema）。可以通过alter session的方式进入别人的房子。<br />
这个时候，你可以看到别人房子里的家具（desc）。<br />
如果你没有特别指定的话，你所做的操作都是针对你当前所在房子中的东西。<br />
至于你是否有权限使用（select）、搬动（update）或者拿走（delete）这些家具就看这个房子的主人有没有给你这样的权限了，<br />
或者你是真个大厦（DB）的老大（DBA）。alter session set schema可以用来代替synonyms。<br />
如果你想调用其他schema的对象（有权限的前提下），又没建synonym，有不想把其他schema名字放如代码中，<br />
就可以先alter session set schema=&lt;其他schema名字&gt;。</p>
</div>
</div>
 <img src ="http://www.blogjava.net/gm_jing/aggbug/292543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-08-25 18:17 <a href="http://www.blogjava.net/gm_jing/articles/292543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle更改数据库字符集编码（转）</title><link>http://www.blogjava.net/gm_jing/articles/235284.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Sun, 19 Oct 2008 03:46:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/235284.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/235284.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/235284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/235284.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/235284.html</trackback:ping><description><![CDATA[<div class="cnt" id="blog_text">
<p>一.准备修改。首先必须用sys连接。</p>
<p>1.修改sys密码.用其他dba权限的账户登陆后输入：alter user sys identified by 新密码;</p>
<p>2.连接刚刚修改的sys（要在登陆状态下）,CONNECT SYS／密码 as sysdba;</p>
<p>二.开始修改:</p>
<p>SQL&gt; shutdown immediate;<br />
SQL&gt; startup mount;<br />
SQL&gt; alter system enable restricted session;<br />
SQL&gt; alter system set job_queue_processes=0;<br />
SQL&gt; alter database open;<br />
SQL&gt; alter database character set internal_use UTF-8;<br />
SQL&gt; shutdown immediate;<br />
SQL&gt; startup<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意：如果没有大对象，在使用过程中进行语言转换没有什么影响，具体过程如下（切记设定的字符集必须是ORACLE支持，不然不能start）</p>
</div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/235284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2008-10-19 11:46 <a href="http://www.blogjava.net/gm_jing/articles/235284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>修改 Oracle9i 8080端口问题</title><link>http://www.blogjava.net/gm_jing/articles/69034.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 11 Sep 2006 13:01:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/69034.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/69034.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/69034.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/69034.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/69034.html</trackback:ping><description><![CDATA[
		<h2>
				<a id="_2576d4f48fe1_HomePageDays_DaysList_ctl11_DayItem_DayList_ctl01_TitleUrl" href="/Victor/archive/2005/06/04/5554.html">修改 Oracle9i 8080端口问题</a>
		</h2>Oracle 9i开始，创建数据库时默认包含了XDB特性。一旦启动了数据库和Listener，Oracle XDB的http服务就占用8080端口，刚好和JBoss、Tomcat等默认端口冲突。除了修改Tomcat等外，还可以修改XDB的配置。<br />Oracle XDB的端口设置不在配置文件中，而是在数据库里。修改XDB的http和ftp服务端口的方法有3种： 
<p>1.使用sys登录Oracle，利用dbms_xdb修改端口设置</p><p>  SQL&gt; -- Change the HTTP/WEBDAV port from 8080 to 8081<br />  SQL&gt; call dbms_xdb.cfg_update(updateXML(<br />    2        dbms_xdb.cfg_get()<br />    3      , '/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()'<br />    4      , 8081))<br />    5  /</p><p>  Call completed. </p><p><br />  SQL&gt; -- Change the FTP port from 2100 to 2111<br />  SQL&gt; call dbms_xdb.cfg_update(updateXML(<br />    2         dbms_xdb.cfg_get()<br />    3       , '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()'<br />    4       , 2111))<br />    5  /</p><p>  Call completed. </p><p><br />  SQL&gt; COMMIT;</p><p>  Commit complete. </p><p><br />  SQL&gt; EXEC dbms_xdb.cfg_refresh;</p><p>  PL/SQL procedure successfully completed.</p><p><br />2.使用OEM console，选择数据库，XML Database，Configuration。更改XDB的有关设置。</p><p>3.去掉数据库的初始化参数：  dispatchers='(PROTOCOL=TCP) (SERVICE=XDB)'，将会禁止XDB的http和ftp服务</p><img src ="http://www.blogjava.net/gm_jing/aggbug/69034.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-09-11 21:01 <a href="http://www.blogjava.net/gm_jing/articles/69034.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle 中select的多种用法</title><link>http://www.blogjava.net/gm_jing/articles/66914.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 31 Aug 2006 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66914.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66914.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66914.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66914.html</trackback:ping><description><![CDATA[<p>1.<br>create table table_tmp as select * from table1 </p>
<p>2.<br>insert into table_tmp<br>(select * from table1)</p>
<p><br>3.<br>update table_tmp <br>set (name,password) = (select name,password from table1)<br><br>4.<br>select tab_name from tables <br>where (tab_name,db_ver) = <br>(&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;select tab_name,db_ver from tab_columns&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;where version = 604<br>) <br></p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-31 17:27 <a href="http://www.blogjava.net/gm_jing/articles/66914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>REF CURSOR 小结</title><link>http://www.blogjava.net/gm_jing/articles/64106.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 17 Aug 2006 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64106.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64106.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64106.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64106.html</trackback:ping><description><![CDATA[
		<p>【REF CURSOR 小结】<br /> <br /> 利用REF CURSOR，可以在程序间传递结果集（一个程序里打开游标变量，在另外的程序里处理数据）。<br />也可以利用REF CURSOR实现BULK SQL，提高SQL性能。</p>
		<p>
				<br /> REF CURSOR分两种：Strong REF CURSOR 和 Weak REF CURSOR。<br />  Strong REF CURSOR:指定retrun type，CURSOR变量的类型必须和return type一致。<br />-&gt;&gt;&gt;DECLARE<br />   TYPE strongcurtyp IS REF CURSOR RETURN emp%ROWTYPE;<br />   emp_cv strongcurtyp;</p>
		<p>
				<br /> Weak REF CURSOR:不指定return type，能和任何类型的CURSOR变量匹配。<br />-&gt;&gt;&gt;DECLARE<br />   TYPE weakcurtyp IS REF CURSOR;<br />   weak_cv weakcurtyp;<br />   any_cv SYS_REFCURSOR; --使用SYS_REFCURSOR可以使变量any_cv跟任何weak REF CURSOR类型匹配。</p>
		<p> </p>
		<p>
				<br />(1)使用Strong REF CURSOR例子 <br />CREATE OR REPLACE PACKAGE emp_data AS<br /> TYPE empcurtyp IS REF CURSOR RETURN emp%rowtype; --定义TYPE as Strong REF CURSOR <br /> PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT); --根据不同的choice选择不同的CURSOR<br /> PROCEDURE retrieve_data(choice INT); --通过调用procedure open_emp_cv，返回指定的结果集。<br />END emp_data;</p>
		<p>CREATE OR REPLACE PACKAGE BODY emp_data AS</p>
		<p> ------------procedure open_emp_cv----------------------- <br /> PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT) IS --emp_cv作为传入/传出的CURSOR PARAMETER<br /> BEGIN<br />  IF choice = 1 THEN<br />   OPEN emp_cv FOR<br />   SELECT * FROM emp WHERE empno &lt; 7800;<br />  ELSIF choice = 2 THEN<br />   OPEN emp_cv FOR<br />   SELECT * FROM emp WHERE SAL &lt; 1000;<br />  ELSIF choice = 3 THEN<br />   OPEN emp_cv FOR<br />   SELECT * FROM emp WHERE ename like 'J%';<br />  END IF;<br /> END;<br /> <br /> <br /> -----------procedure retrieve_data----------------------- <br /> PROCEDURE retrieve_data(choice INT) IS<br />  return_cv empcurtyp; --定义传入open_emp_cv的CURSOR变量<br />  return_row emp%ROWTYPE;<br />  invalid_choice EXCEPTION;<br /> BEGIN<br />  open_emp_cv(return_cv, choice); --调用 procedure OPEN_EMP_CV<br /> <br />  IF choice = 1 THEN<br />   DBMS_OUTPUT.PUT_LINE('EMPLOYEES with empno less than 7800');<br />  ELSIF choice = 2 THEN<br />   DBMS_OUTPUT.PUT_LINE('EMPLOYEES with salary less than 1000');<br />  ELSIF choice = 3 THEN<br />   DBMS_OUTPUT.PUT_LINE('EMPLOYEES with name starts with ''J''');<br />  ELSE<br />   RAISE invalid_choice;<br />  END IF;<br /> <br />  LOOP<br />  FETCH return_cv INTO return_row;<br />  EXIT WHEN return_cv%NOTFOUND;<br />  <br />   DBMS_OUTPUT.PUT_LINE(return_row.empno || '--' || return_row.ename || '--' || return_row.sal);<br />  END LOOP;<br /> <br /> EXCEPTION<br />  WHEN invalid_choice THEN<br />   DBMS_OUTPUT.PUT_LINE('The CHOICE should be in one of (1,2,3)!');<br />  WHEN OTHERS THEN <br />   DBMS_OUTPUT.PUT_LINE('Errors in procedure RETRIEVE_DATA!');<br /> END;</p>
		<p>END emp_data;</p>
		<p>
				<br />================================<br />执行：<br />SQL&gt; EXEC emp_data.retrieve_data(1);<br />EMPLOYEES with empno less than 7800<br />7369--SMITH--800<br />7499--ALLEN--1600<br />7521--WARD--1250<br />7566--JONES--2975<br />7654--MARTIN--1250<br />7698--BLAKE--2850<br />7782--CLARK--2450<br />7788--SCOTT--3000<br />PL/SQL procedure successfully completed</p>
		<p>SQL&gt; EXEC emp_data.retrieve_data(2);<br />EMPLOYEES with salary less than 1000<br />7369--SMITH--800<br />7900--JAMES--950<br />PL/SQL procedure successfully completed</p>
		<p>SQL&gt; EXEC emp_data.retrieve_data(3);<br />EMPLOYEES with name starts with 'J'<br />7566--JONES--2975<br />7900--JAMES--950<br />PL/SQL procedure successfully completed</p>
		<p>SQL&gt; EXEC emp_data.retrieve_data(34);<br />The CHOICE should be in one of (1,2,3)!<br />PL/SQL procedure successfully completed</p>
		<p>
				<br />(2)使用Weak REF CURSOR例子 <br />-----------procedure open_cv----------------------------<br />create or replace procedure open_cv(choice IN INT, return_cv OUT SYS_REFCURSOR) is<br />--参数return_cv为weak REF CURSOR,利用SYS_CURSOR来定义<br />begin<br /> if choice = 1 then<br />  open return_cv for 'select * from emp';<br /> elsif choice = 2 then<br />  open return_cv for 'select * from dept';<br /> end if;<br />end open_cv;</p>
		<p>
				<br />-----------procedure retrieve_data----------------------------<br />create or replace procedure retrieve_data(choice IN INT) is<br /> emp_rec emp%rowtype;<br /> dept_rec dept%rowtype;<br /> return_cv SYS_REFCURSOR;<br /> invalid_choice exception;<br />begin<br /> if choice=1 then<br />  dbms_output.put_line('employee information');<br />  open_cv(1,return_cv); --调用procedure open_cv;<br />  loop<br />  fetch return_cv into emp_rec;<br />  exit when return_cv%notfound;<br />   dbms_output.put_line(emp_rec.empno||'-'||emp_rec.ename||'-'||emp_rec.sal);<br />  end loop;<br /> elsif choice=2 then<br />  dbms_output.put_line('department information');<br />  open_cv(2,return_cv);<br />  loop<br />  fetch return_cv into dept_rec;<br />  exit when return_cv%notfound;<br />   dbms_output.put_line(dept_rec.deptno||'-'||dept_rec.dname||'-'||dept_rec.loc);<br />  end loop;<br /> else<br />  raise invalid_choice;<br /> end if;</p>
		<p>exception<br /> when invalid_choice then<br />  dbms_output.put_line('The CHOICE should be one of 1 and 2!');<br /> when others then<br />  dbms_output.put_line('Errors in procedure retrieve_data');<br />end retrieve_data;</p>
		<p>-----------------------------------------------------------------</p>
		<p>执行：<br />SQL&gt; exec retrieve_data(1);<br />employee information<br />7369-SMITH-800<br />7499-ALLEN-1600<br />7521-WARD-1250<br />7566-JONES-2975<br />7654-MARTIN-1250<br />7698-BLAKE-2850<br />......<br />PL/SQL procedure successfully completed</p>
		<p>SQL&gt; exec retrieve_data(2);<br />department information<br />10-ACCOUNTING-NEW YORK<br />20-RESEARCH-DALLAS<br />30-SALES-CHICAGO<br />40-OPERATIONS-BOSTON<br />PL/SQL procedure successfully completed</p>
		<p> </p>
		<p>(3)用REF CURSOR实现BULK功能 <br />1. To speed up INSERT, UPDATE, and DELETE statements, enclose the SQL statement within a PL/SQL FORALL statement instead of a loop construct.<br />2. To speed up SELECT statements, include the BULK COLLECT INTO clause in the SELECT statement instead of using INTO.</p>
		<p> </p>
		<p>SQL&gt; create table tab2 as select empno ID, ename NAME, sal SALARY from emp where 1=2;<br />Table created</p>
		<p>create or replace procedure REF_BULK is<br /> type empcurtyp is ref cursor;<br /> type idlist is table of emp.empno%type;<br /> type namelist is table of emp.ename%type;<br /> type sallist is table of emp.sal%type;<br /> <br /> emp_cv empcurtyp;<br /> ids idlist;<br /> names namelist;<br /> sals sallist;<br /> <br /> row_cnt number;<br />begin<br /> open emp_cv for<br />  select empno, ename, sal from emp;<br />  fetch emp_cv BULK COLLECT INTO ids, names, sals; --BULK COLLECT INTO instead of INTO<br /> close emp_cv;</p>
		<p> for i in ids.first .. ids.last loop<br />  dbms_output.put_line('id=' || ids(i) || ' name=' || names(i) || ' salary=' || sals(i));<br /> end loop;</p>
		<p> forall i in ids.first .. ids.last --FORALL instead of FOR ...LOOP<br />  insert into tab2 values (ids(i), names(i), sals(i));<br /> commit;</p>
		<p> select count(*) into row_cnt from tab2;<br />  dbms_output.put_line('-----------------------------------');<br />  dbms_output.put_line('The row number of tab2 is ' || row_cnt);<br /> end REF_BULK;</p>
		<p>
				<br />------------------------------------------------------------</p>
		<p>执行：</p>
		<p>SQL&gt; exec ref_bulk;</p>
		<p>id=7369 name=SMITH salary=800<br />id=7499 name=ALLEN salary=1600<br />id=7521 name=WARD salary=1250<br />id=7566 name=JONES salary=2975<br />id=7654 name=MARTIN salary=1250<br />id=7698 name=BLAKE salary=2850<br />id=7782 name=CLARK salary=2450<br />id=7788 name=SCOTT salary=3000<br />id=7839 name=KING salary=5000<br />id=7844 name=TURNER salary=1500<br />id=7876 name=ADAMS salary=1100<br />id=7900 name=JAMES salary=950<br />id=7902 name=FORD salary=3000<br />id=7934 name=MILLER salary=1300<br />-----------------------------------<br />The row number of tab2 is 14</p>
		<p>PL/SQL procedure successfully completed</p>
		<p> </p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/64106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-17 13:52 <a href="http://www.blogjava.net/gm_jing/articles/64106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle 中分页的处理</title><link>http://www.blogjava.net/gm_jing/articles/64105.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 17 Aug 2006 05:51:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64105.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64105.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64105.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64105.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64105.html</trackback:ping><description><![CDATA[<p>[注意]<br />
1、rownum 不能直接使用&gt; .<br />
2、需要先排序，过滤以后再处理rownum</p>
<p>i、minus&nbsp;&nbsp; <br />
这个方法因为用到了minus操作符，所以速度会受影响</p>
<p>select rownum,c1.* from (select t.* from carrier t where .... order by...) c1 where rownum &lt;= 8<br />
minus<br />
select rownum,c2.* from (select t.* from carrier t where .... order by...) c2 where rownum &lt;= 8</p>
<p>ii、select嵌套(3层)。</p>
<p>SELECT *<br />
&nbsp; FROM (SELECT rownum rownumber, c.*<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select t.* from carrier t where .... order by .. .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) c<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) cc<br />
&nbsp;WHERE cc.rownumber &gt; 8<br />
&nbsp;&nbsp; and cc.rownumber &lt;= 10<br />
</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/64105.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-17 13:51 <a href="http://www.blogjava.net/gm_jing/articles/64105.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>