﻿<?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>IT博客-沙龙之窝-随笔分类-数据库</title><link>http://www.cnitblog.com/salemsu/category/7417.html</link><description>我的心路历程及工作经验分享,希望诸位能有所感悟和共鸣，能在尘世中找到自己的路。毕竟，路终究还是要自己走。</description><language>zh-cn</language><lastBuildDate>Sat, 08 Oct 2011 06:24:47 GMT</lastBuildDate><pubDate>Sat, 08 Oct 2011 06:24:47 GMT</pubDate><ttl>60</ttl><item><title>SQL Server和Oracle的常用函数对比</title><link>http://www.cnitblog.com/salemsu/archive/2008/07/30/47302.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Wed, 30 Jul 2008 07:35:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/30/47302.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/47302.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/30/47302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/47302.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/47302.html</trackback:ping><description><![CDATA[<p>---------数学函数</p>
<p>1.绝对值<br>S:select abs(-1) value<br>O:select abs(-1) value from dual</p>
<p>2.取整(大)<br>S:select ceiling(-1.001) value<br>O:select ceil(-1.001) value from dual</p>
<p>3.取整（小）<br>S:select floor(-1.001) value<br>O:select floor(-1.001) value from dual</p>
<p>4.取整（截取）<br>S:select cast(-1.002 as int) value<br>O:select trunc(-1.002) value from dual</p>
<p>5.四舍五入<br>S:select round(1.23456,4) value 1.23460<br>O:select round(1.23456,4) value from dual 1.2346</p>
<p>6.e为底的幂<br>S:select Exp(1) value 2.7182818284590451<br>O:select Exp(1) value from dual 2.71828182</p>
<p>7.取e为底的对数<br>S:select log(2.7182818284590451) value 1<br>O:select ln(2.7182818284590451) value from dual; 1</p>
<p>8.取10为底对数<br>S:select log10(10) value 1<br>O:select log(10,10) value from dual; 1</p>
<p>9.取平方<br>S:select SQUARE(4) value 16<br>O:select power(4,2) value from dual 16</p>
<p>10.取平方根<br>S:select SQRT(4) value 2<br>O:select SQRT(4) value from dual 2</p>
<p>11.求任意数为底的幂<br>S:select power(3,4) value 81<br>O:select power(3,4) value from dual 81</p>
<p>12.取随机数<br>S:select rand() value<br>O:select sys.dbms_random.value(0,1) value from dual;</p>
<p>13.取符号<br>S:select sign(-8) value -1<br>O:select sign(-8) value from dual -1</p>
<p>----------三角函数相关</p>
<p>14.圆周率<br>S:SELECT PI() value 3.1415926535897931<br>O:不知道</p>
<p>15.sin,cos,tan 参数都以弧度为单位<br>例如：select sin(PI()/2) value 得到1（SQLServer）</p>
<p>16.Asin,Acos,Atan,Atan2 返回弧度</p>
<p>17.弧度角度互换(SQLServer，Oracle不知道)<br>DEGREES：弧度-〉角度<br>RADIANS：角度-〉弧度</p>
<p>---------数值间比较</p>
<p>18. 求集合最大值<br>S:select max(value) value from<br>(select 1 value<br>union<br>select -2 value<br>union<br>select 4 value<br>union<br>select 3 value)a</p>
<p>O:select greatest(1,-2,4,3) value from dual</p>
<p>19. 求集合最小值<br>S:select min(value) value from<br>(select 1 value<br>union<br>select -2 value<br>union<br>select 4 value<br>union<br>select 3 value)a</p>
<p>O:select least(1,-2,4,3) value from dual</p>
<p>20.如何处理null值(F2中的null以10代替)<br>S:select F1,IsNull(F2,10) value from Tbl<br>O:select F1,nvl(F2,10) value from Tbl</p>
<p>--------字符串函数</p>
<p>21.求字符序号<br>S:select ascii('a') value<br>O:select ascii('a') value from dual</p>
<p>22.从序号求字符<br>S:select char(97) value<br>O:select chr(97) value from dual</p>
<p>23.连接<br>S:select '11'+'22'+'33' value<br>O:select CONCAT('11','22')||33 value from dual</p>
<p>23.子串位置 --返回3<br>S:select CHARINDEX('s','sdsq',2) value<br>O:select INSTR('sdsq','s',2) value from dual</p>
<p>23.模糊子串的位置 --返回2,参数去掉中间%则返回7<br>S:select patindex('%d%q%','sdsfasdqe') value<br>O:oracle没发现，但是instr可以通过第四个参数控制出现次数<br>select INSTR('sdsfasdqe','sd',1,2) value from dual 返回6</p>
<p>24.求子串<br>S:select substring('abcd',2,2) value<br>O:select substr('abcd',2,2) value from dual</p>
<p>25.子串代替 返回aijklmnef<br>S:SELECT STUFF('abcdef', 2, 3, 'ijklmn') value<br>O:SELECT Replace('abcdef', 'bcd', 'ijklmn') value from dual</p>
<p>26.子串全部替换<br>S:Replace<br>O:select Translate('fasdbfasegas','fa','我' ) value from dual</p>
<p>27.长度<br>S:len,datalength<br>O:length</p>
<p>28.大小写转换 lower,upper</p>
<p>29.单词首字母大写<br>S:没发现<br>O:select INITCAP('abcd dsaf df') value from dual</p>
<p>30.左补空格（LPAD的第一个参数为空格则同space函数）<br>S:select space(10)+'abcd' value<br>O:select LPAD('abcd',14) value from dual</p>
<p>31.右补空格（RPAD的第一个参数为空格则同space函数）<br>S:select 'abcd'+space(10) value<br>O:select RPAD('abcd',14) value from dual</p>
<p>32.删除空格<br>S:ltrim,rtrim<br>O:ltrim,rtrim,trim</p>
<p>33. 重复字符串<br>S:select REPLICATE('abcd',2) value<br>O:没发现</p>
<p>34.发音相似性比较(这两个单词返回值一样，发音相同)<br>S:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe')<br>O:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe') from dual<br>SQLServer中用SELECT DIFFERENCE('Smithers', 'Smythers') 比较soundex的差<br>返回0-4，4为同音，1最高</p>
<p>--------------日期函数</p>
<p>35.系统时间<br>S:select getdate() value<br>O:select sysdate value from dual</p>
<p>36.前后几日<br>直接与整数相加减</p>
<p>37.求日期<br>S:select convert(char(10),getdate(),20) value<br>O:select trunc(sysdate) value from dual<br>select to_char(sysdate,'yyyy-mm-dd') value from dual</p>
<p>38.求时间<br>S:select convert(char(8),getdate(),108) value<br>O:select to_char(sysdate,'hh24:mm:ss') value from dual</p>
<p>39.取日期时间的其他部分<br>S:DATEPART 和 DATENAME 函数 （第一个参数决定）<br>O:to_char函数 第二个参数决定</p>
<p>参数---------------------------------下表需要补充<br>year yy, yyyy<br>quarter qq, q (季度)<br>month mm, m (m O无效)<br>dayofyear dy, y (O表星期)<br>day dd, d (d O无效)<br>week wk, ww (wk O无效)<br>weekday dw (O不清楚)<br>Hour hh,hh12,hh24 (hh12,hh24 S无效)<br>minute mi, n (n O无效)<br>second ss, s (s O无效)<br>millisecond ms (O无效)<br>----------------------------------------------</p>
<p>40.当月最后一天<br>S:不知道<br>O:select LAST_DAY(sysdate) value from dual</p>
<p>41.本星期的某一天（比如星期日）<br>S:不知道<br>O:SELECT Next_day(sysdate,7) vaule FROM DUAL;</p>
<p>42.字符串转时间<br>S:可以直接转或者select cast('2004-09-08'as datetime) value<br>O:SELECT To_date('2004-01-05 22:09:38','yyyy-mm-dd hh24-mi-ss') vaule FROM DUAL;</p>
<p>43.求两日期某一部分的差（比如秒）<br>S:select datediff(ss,getdate(),getdate()+12.3) value<br>O:直接用两个日期相减（比如d1-d2=12.3）<br>SELECT (d1-d2)*24*60*60 vaule FROM DUAL;</p>
<p>44.根据差值求新的日期（比如分钟）<br>S:select dateadd(mi,8,getdate()) value<br>O:SELECT sysdate+8/60/24 vaule FROM DUAL;</p>
<p>45.求不同时区时间<br>S:不知道<br>O:SELECT New_time(sysdate,'ydt','gmt' ) vaule FROM DUAL;</p>
<p>-----时区参数,北京在东8区应该是Ydt-------<br>AST ADT 大西洋标准时间<br>BST BDT 白令海标准时间<br>CST CDT 中部标准时间<br>EST EDT 东部标准时间<br>GMT 格林尼治标准时间<br>HST HDT 阿拉斯加—夏威夷标准时间<br>MST MDT 山区标准时间<br>NST 纽芬兰标准时间<br>PST PDT 太平洋标准时间<br>YST YDT YUKON标准时间</p>
<p>Oracle支持的字符函数和它们的Microsoft SQL Server等价函数:</p>
<p>函数 Oracle Microsoft SQL　Server<br>把字符转换为ASCII ASCII ASCII<br>字串连接 CONCAT (expression + expression)<br>把ASCII转换为字符 CHR CHAR<br>返回字符串中的开始字符（左起） INSTR CHARINDEX<br>把字符转换为小写 LOWER LOWER<br>把字符转换为大写 UPPER UPPER<br>填充字符串的左边 LPAD N/A<br>清除开始的空白 LTRIM LTRIM<br>清除尾部的空白 RTRIM RTRIM<br>字符串中的起始模式（pattern） INSTR PATINDEX<br>多次重复字符串 RPAD REPLICATE<br>字符串的语音表示 SOUNDEX SOUNDEX<br>重复空格的字串 RPAD SPACE<br>从数字数据转换为字符数据 TO_CHAR STR<br>子串 SUBSTR SUBSTRING<br>替换字符 REPLACE STUFF<br>将字串中的每个词首字母大写 INITCAP N/A<br>翻译字符串 TRANSLATE N/A<br>字符串长度 LENGTH DATELENGTH or LEN<br>列表中最大的字符串 GREATEST N/A<br>列表中最小的字符串 LEAST N/A<br>如果为NULL则转换字串 NVL ISNULL</p>
<p>日期函数</p>
<p>函数 Oracle Microsoft SQL　Server<br>日期相加 (date column +/- value) or<br>ADD_MONTHS DATEADD<br>两个日期的差 (date column +/- value) or<br>MONTHS_BETWEEN DATEDIFF<br>当前日期和时间 SYSDATE GETDATE()<br>一个月的最后一天 LAST_DAY N/A<br>时区转换 NEW_TIME N/A<br>日期后的第一个周日 NEXT_DAY N/A<br>代表日期的字符串 TO_CHAR DATENAME<br>代表日期的整数 TO_NUMBER<br>(TO_CHAR)) DATEPART<br>日期舍入 ROUND CONVERT<br>日期截断 TRUNC CONVERT<br>字符串转换为日期 TO_DATE CONVERT<br>如果为NULL则转换日期 NVL ISNULL</p>
<p>转换函数</p>
<p>函数 Oracle Microsoft SQL　Server<br>数字转换为字符 TO_CHAR CONVERT<br>字符转换为数字 TO_NUMBER CONVERT<br>日期转换为字符 TO_CHAR CONVERT<br>字符转换为日期 TO_DATE CONVERT<br>16进制转换为2进制 HEX_TO_RAW CONVERT<br>2进制转换为16进制 RAW_TO_HEX CONVERT</p>
<p>其它行级别的函数</p>
<p>函数 Oracle Microsoft SQL　Server<br>返回第一个非空表达式 DECODE COALESCE<br>当前序列值 CURRVAL N/A<br>下一个序列值 NEXTVAL N/A<br>如果exp1 = exp2, 返回null DECODE NULLIF<br>用户登录账号ID数字 UID SUSER_ID<br>用户登录名 USER SUSER_NAME<br>用户数据库ID数字 UID USER_ID<br>用户数据库名 USER USER_NAME<br>当前用户 CURRENT_USER CURRENT_USER<br>用户环境(audit trail) USERENV N/A<br>在CONNECT BY子句中的级别 LEVEL N/A</p>
<p>合计函数</p>
<p>函数 Oracle Microsoft SQL　Server<br>Average AVG AVG<br>Count COUNT COUNT<br>Maximum MAX MAX<br>Minimum MIN MIN<br>Standard deviation STDDEV STDEV or STDEVP<br>Summation SUM SUM<br>Variance VARIANCE VAR or VARP</p>
<p>Oracle还有一个有用的函数EXTRACT,提取并且返回日期时间或时间间隔表达式中特定的时间域:<br>EXTRACT(YEAR FROM 日期)</p>
<img src ="http://www.cnitblog.com/salemsu/aggbug/47302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-30 15:35 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/30/47302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个朋友帮忙写的基于Oracle 实现进销存的触发器</title><link>http://www.cnitblog.com/salemsu/archive/2008/07/18/46878.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Fri, 18 Jul 2008 05:40:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/18/46878.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/46878.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/18/46878.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/46878.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/46878.html</trackback:ping><description><![CDATA[<p>CREATE OR REPLACE TRIGGER TRG_cux_wms_transaction_line<br>&nbsp; before insert or update or delete on cux_wms_transaction_line<br>&nbsp; REFERENCING NEW AS NEW OLD AS OLD<br>&nbsp; for each row<br>declare<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ai_in_count number;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ai_out_count number;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ai_abs number;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; --源仓区游标&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Cursor temp_in_cursor is<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select count(*)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :new.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.INVENTORY_CODE = cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.batchno= cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.source_loc_code = cux_wms_stock.location_code;<br>&nbsp;&nbsp;&nbsp; --目标仓区游标&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Cursor temp_out_cursor is<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select count(*)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :new.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.INVENTORY_CODE = cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.batchno= cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.intent_loc_code = cux_wms_stock.location_code;<br>begin<br>&nbsp; <br>&nbsp; --设定计算方向<br>&nbsp; --case :new.operation_Mark;<br>&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp; when 'I' then ai_abs := 1;<br>&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp; when 'O' then ai_abs := -1;<br>&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp; when 'M' then ai_abs := 1;<br>&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp; else ai_abs := 0;<br>&nbsp; --end case;<br>&nbsp; ai_abs := 1;<br>&nbsp; if :new.operation_Mark = 'I' then--设定计算方向<br>&nbsp;&nbsp;&nbsp;&nbsp; ai_abs := 1;<br>&nbsp; end if;<br>&nbsp; if :new.operation_Mark = 'O' then--设定计算方向<br>&nbsp;&nbsp;&nbsp;&nbsp; ai_abs := -1;<br>&nbsp; end if; <br>&nbsp; if :new.operation_Mark = 'M' then--设定计算方向<br>&nbsp;&nbsp;&nbsp;&nbsp; ai_abs := -1;<br>&nbsp; end if;<br>&nbsp; if :new.operation_Mark = 'C' then--设定计算方向<br>&nbsp;&nbsp;&nbsp;&nbsp; ai_abs := 0;<br>&nbsp; end if;<br>&nbsp; --打开源仓区的游标<br>&nbsp; open temp_in_cursor;<br>&nbsp; fetch temp_in_cursor into ai_in_count;<br>&nbsp; <br>&nbsp; if ai_in_count &gt; 0 then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set cux_wms_stock.quantity = cux_wms_stock.quantity + :new.CASE_NUMBER * ai_abs,LAST_UPDATE_DATE=(select sysdate from dual),LAST_UPDATED_BY=:new.LAST_UPDATED_BY<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :new.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.INVENTORY_CODE = cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.batchno = cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.source_loc_code= cux_wms_stock.location_code;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if :new.operation_Mark = 'M' then--转移模式<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --打开目标仓区的游标<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; open temp_out_cursor;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fetch temp_out_cursor into ai_out_count;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ai_out_count &gt; 0 then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set cux_wms_stock.quantity = cux_wms_stock.quantity + :new.CASE_NUMBER * ai_abs,LAST_UPDATE_DATE=(select sysdate from dual),LAST_UPDATED_BY=:new.LAST_UPDATED_BY<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :new.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.INVENTORY_CODE=cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.batchno = cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :new.intent_loc_code= cux_wms_stock.location_code;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Insert into CUX_WMS_STOCK(STOCK_ID,ITEM_BARCODE,SPLINT_BARCODE,ORGANIZATION_ID,ORG_ID,INVENTORY_CODE,<br>LOCATION_CODE,BATCH_NUMBER,QUANTITY,CREATION_DATE,CREATED_BY,LAST_UPDATE_DATE,<br>LAST_UPDATED_BY,INVENTORY_ITEM_ID) values(CUX_WMS_STOCK_ID_S.nextval,:new.item_barcode,:new.splint_barcode,:new.organization_id,:new.org_id,<br>:new.INVENTORY_CODE,:new.intent_loc_code,:new.batchno,:new.CASE_NUMBER * (-ai_abs),:new.CREATION_DATE,:new.CREATED_BY,:new.LAST_UPDATE_DATE,:new.LAST_UPDATED_BY,0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end if;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close temp_out_cursor;<br>&nbsp;&nbsp;&nbsp;&nbsp; end if;<br>&nbsp; else<br>&nbsp;&nbsp;&nbsp; if :old.org_id is null then --增加模式时<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Insert into CUX_WMS_STOCK(STOCK_ID,ITEM_BARCODE,SPLINT_BARCODE,ORGANIZATION_ID,ORG_ID,INVENTORY_CODE,<br>LOCATION_CODE,BATCH_NUMBER,QUANTITY,CREATION_DATE,CREATED_BY,LAST_UPDATE_DATE,<br>LAST_UPDATED_BY,INVENTORY_ITEM_ID) values(CUX_WMS_STOCK_ID_S.nextval,:new.item_barcode,:new.splint_barcode,:new.organization_id,:new.org_id,<br>:new.INVENTORY_CODE,:new.intent_loc_code,:new.batchno,:new.CASE_NUMBER * ai_abs,:new.CREATION_DATE,:new.CREATED_BY,:new.LAST_UPDATE_DATE,:new.LAST_UPDATED_BY,0);<br>&nbsp;&nbsp;&nbsp; end if;<br>&nbsp; end if;<br>&nbsp; <br>&nbsp;if :old.org_id is not null then --修改或者删除模式，需要回滚原记录的数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set cux_wms_stock.quantity = cux_wms_stock.quantity + :old.CASE_NUMBER * ai_abs,LAST_UPDATE_DATE=(select sysdate from dual),LAST_UPDATED_BY=:old.LAST_UPDATED_BY<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :old.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.INVENTORY_CODE=cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.batchno = cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.source_loc_code= cux_wms_stock.location_code;<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if :old.operation_Mark = 'M' then--转移模式</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update cux_wms_stock<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set cux_wms_stock.quantity = cux_wms_stock.quantity + :old.CASE_NUMBER * (-ai_abs),LAST_UPDATE_DATE=(select sysdate from dual),LAST_UPDATED_BY=:old.LAST_UPDATED_BY<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where :old.organization_id = cux_wms_stock.organization_id and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.org_id = cux_wms_stock.org_id and<br>&nbsp;&nbsp;&nbsp;&nbsp; :old.INVENTORY_CODE=cux_wms_stock.INVENTORY_CODE and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.splint_barcode = cux_wms_stock.splint_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.item_barcode = cux_wms_stock.item_barcode and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.batchno = cux_wms_stock.batch_number and<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :old.intent_loc_code= cux_wms_stock.location_code;</p>
<p>&nbsp;&nbsp;&nbsp; end if;<br>&nbsp;end if; </p>
<p>&nbsp;close temp_in_cursor;<br>&nbsp;delete from cux_wms_stock where quantity=0;<br>end TRG_CUX;<br>/<br></p>
<img src ="http://www.cnitblog.com/salemsu/aggbug/46878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-18 13:40 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/18/46878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET调用oracle的存储过程返回记录集 </title><link>http://www.cnitblog.com/salemsu/archive/2008/07/18/46877.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Fri, 18 Jul 2008 05:36:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/18/46877.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/46877.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/18/46877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/46877.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/46877.html</trackback:ping><description><![CDATA[<p>长期以来，我一直用的是 MS SQL Server / Access 数据库，通过 .NET 访问 MS 自家的东西几乎没碰到过什么麻烦。最近项目中要用 Oracle 作为数据库，学习研究了一些 .NET 访问 Oracle 的东西，发现问题倒真的不少。<br><br></p>
<p>1。System.Data.OracleClient 和 System.Data.OleDb 命名空间</p>
<p>虽然通过这两个命名空间的类都可以访问 Oracle 数据库，但和 SQL Server 类似的（System.Data.SqlClient 命名空间的类效率要比 System.Data.OleDb 命名空间中的类高一些），System.Data.OracleClient 命名空间中的类要比 System.Data.OleDb 命名空间的类效率高一些（这一点我没有亲自验证，但大多数地方都会这么说，而且既然专门为 Oracle 作的东西理论上也应该专门作过针对性的优化）。</p>
<p>当然还有另一点就是从针对性上说，System.Data.OracleClient 要更好一些：</p>
<p>比如数据类型，System.Data.OleDb.OleDbType 枚举中所列的就没有 System.Data.OracleClient.OracleType 枚举中的那些有针对性；另外，Oracle 的 Number 类型如果数字巨大，超出&nbsp;.NET 数据类型范围的情况中，就必须使用 System.Data.OracleClient 中的专门类 --&nbsp;OracleNumber 类型。</p>
<p>好了，不再赘述这两个的比较，下面主要讨论 System.Data.OracleClient 命名空间中的类型，即 ADO.NET for Oracle Data Provider (数据提供程序)。</p>
<br>注:如果要使用Oracle的cursor(游标)返回多记录集,请使用System.Data.OracleClient,因为System.Data.OleDb 没有这种数据类型.(当时这个问题折腾我几天了)<br><br>
<p>2。数据库连接：</p>
<p>无论是 System.Data.OleDb 还是 System.Data.OracleClient 访问 Oracle 都需要在 .NET 运行的机器（ASP.NET 中就是 Web 服务器）安装 Oracle 客户端组件。（这一点是和 MS 的两种数据库不同的，MS 的东西安装 MDAC: Microsoft Data Access Component 2.6 以上版本后，就无须再安装 SQL Server 客户端或者 Office 软件，就能访问。）</p>
<p>System Requirements：</p>
<p>(1)如用 System.Data.OracleClient 访问 Oracle，客户端组件版本应在 Oracle 8i Client Release 3 (8.1.7)以上版本。MS 只确保访问 Oracle 8.1.6、Oracle 8.1.7、Oracle 9i 服务器时的情况。MDAC 2.6 以上。</p>
<p>(2)如用 System.Data.OleDb 访问 Oracle，客户端组件版本 7.3.3.4.0 以上或 8.1.7.4.1 以上。MDAC 2.6 以上。</p>
<p>如服务器为 Oracle8i 以上，客户端组件版本应为 8.0.4.1.1c。</p>
<p>在 .NET 运行的机器中，安装 Oracle&nbsp;客户端，然后打开 Net Manager (Oracle 9i) / Easy Config (Oracle 8i) 按你以前的经验设置本地服务的映射（这里的服务名将用于数据库连接串）。</p>
<p>System.Data.OracleClient 中访问 Oracle 数据库的连接串是：</p>
<p>User ID=用户名; Password=密码; Data Source=服务名</p>
<p>(上述为一般的连接串，详细的连接串项目可以在 System.Data.OracleClient.OracleConnection.ConnectionString 属性的文档中找到。)</p>
<p>System.Data.OleDb 中的访问 Oracle 数据库的连接串是：</p>
<p>Provider=MSDAORA.1; User ID=用户名; Password=密码; Data Source=服务名<br><br><br></p>
<p>3。Oracle 中的数据类型：</p>
<p>Oracle 的数据类型和 SQL Server 相比，要&#8220;奇怪&#8221;一些：SQL Server 的大多数据类型很容易找到 .NET 中比较接近的类型，Oracle 中的类型就离 .NET 类型远了许多，毕竟 Oracle 是和 Java 亲近的数据库。</p>
<ul>
    <li>number: 数字类型，一般是 Number(M,N)，M是有效数字，N是小数点后的位数（默认0），这个是按十进制说的。
    <li>nvarchar2: 可变长字符型（Unicode），这个比较像 SQL Server 的 nvarchar（但不知 Oracle 为什么加了个&#8220;2&#8221;）。（去掉&#8220;n&#8221;为非 Unicode 的，下同。）
    <li>nchar: 定长字符型(Unicode)。
    <li>nclob: &#8220;写作文&#8221;的字段，存储大量字符（Unicode）时用。
    <li>date: 日期类型，比较接近 SQL Server 的 datetime。</li>
</ul>
<p>Oracle 中字段不能是 bit 或者 bool 之类的类型，一般是 number(1) 代替的。</p>
<p>和 SQL Server 一样在 SQL 命令中，字符类型需要用单引号（'）隔开，两个单引号（''）是单引号的字符转义（比如： I'm fat. 写入一个 SQL 命令是： UPDATE ... SET ...='I''m fat.' ...）。</p>
<p>比较特殊的是日期类型：比如要写入 2004-7-20 15:20:07 这个时刻需要如下写：</p>
<p>UPDATE ... SET ... = TIMESTAMP '2004-7-20 15:20:07' ...</p>
<p>注意这里使用了 TIMESTAMP 关键字，并使用单引号隔开；另外请注意日期格式，上面的格式是可识别的，Oracle 识别的格式没有 SQL Server 那般多。这是和 SQL Server 不同的地方。</p>
<p>顺便提一句：Access 中的日期类型是用井号(#)隔开的，UPDATE ... SET ... = #2004-7-20 15:20:07# ...<br><br><br></p>
<p>4。访问 Oracle 过程/函数（1）</p>
<p>SQL Server 作程序时经常使用存储过程，Oracle 里也可以使用过程，还可以使用函数。Oracle 的过程似乎是不能有返回值的，有返回值的就是函数了（这点有些像 BASIC，函数/过程区分的很细致。SQL Server 存储过程是可以有返回值的）。</p>
<p>.NET 访问 Oracle 过程/函数的方法很类似于 SQL Server，例如：</p>
<p>OracleParameter[] parameters = {<br>&nbsp;&nbsp;&nbsp; new OracleParameter("ReturnValue", OracleType.Int32, 0, ParameterDirection.ReturnValue,&nbsp;true, 0, 0, "",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataRowVersion.Default, Convert.DBNull )<br>&nbsp;&nbsp;&nbsp; new OracleParameter("参数1",&nbsp;OracleType.NVarChar, 10),<br>&nbsp;&nbsp;&nbsp; new OracleParameter("参数2",&nbsp;&nbsp;OracleType.DateTime),<br>&nbsp;&nbsp;&nbsp; new OracleParameter("参数3",&nbsp;&nbsp;OracleType.Number, 1)<br>&nbsp;};<br><br>parameters[1].Value = "test";<br>parameters[2].Value = DateTime.Now;<br>parameters[3].Value = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 也可以是 new OracleNumber(1);</p>
<p>OracleConnection connection = new OracleConnection( ConnectionString );<br>OracleCommand command = new OracleCommand("函数/程名", connection);<br>command.CommandType = CommandType.StoredProcedure;<br><br>foreach(OracleParameter parameter in parameters)<br>&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters.Add( parameter );<br><br>connection.Open();<br>command.ExecuteNonQuery();<br>int returnValue = parameters[0].Value; //接收函数返回值<br>connection.Close();</p>
<p>Parameter 的 DbType 设定请参见 System.Data.OracleClient.OracleType 枚举的文档，比如：Oracle 数据库中 Number 类型的参数的值可以用 .NET decimal 或 System.Data.OracleClient.OracleNumber 类型指定； Integer 类型的参数的值可以用 .NET int 或 OracleNumber 类型指定。等等。</p>
<p>上面例子中已经看到函数返回值是用名为&#8220;ReturnValue&#8221;的参数指定的，该参数为 ParameterDirection.ReturnValue 的参数。</p>
<p>5。访问 Oracle 过程/函数 (2)</p>
<p>不返回记录集（没有 SELECT 输出）的过程/函数，调用起来和 SQL Server 较为类似。但如果想通过过程/函数返回记录集，在 Oracle 中就比较麻烦一些了。</p>
<p>在 SQL Server 中，如下的存储过程：</p>
<p>CREATE PROCEDURE GetCategoryBooks<br>(<br>&nbsp;&nbsp;&nbsp; @CategoryID int<br>)<br>AS<br>SELECT * FROM Books<br>WHERE CategoryID = @CategoryID<br>GO</p>
<p>在 Oracle 中，请按以下步骤操作：</p>
<p>(1)创建一个包，含有一个游标类型：（一个数据库中只需作一次）</p>
<p>CREATE OR REPLACE PACKAGE Test<br>&nbsp; AS<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TYPE Test_CURSOR IS REF CURSOR;<br>END Test;</p>
<p>(2)过程：</p>
<p>CREATE OR REPLACE PROCEDURE GetCategoryBooks<br>(<br>&nbsp;&nbsp;&nbsp;&nbsp; p_CURSOR&nbsp;out Test.Test_CURSOR,&nbsp;&nbsp;&nbsp; --&nbsp;这里是上面包中的类型，输出参数<br>&nbsp;&nbsp;&nbsp;&nbsp; p_CatogoryID INTEGER<br>)<br>AS<br>BEGIN<br>&nbsp;&nbsp;&nbsp;&nbsp; OPEN p_CURSOR FOR<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT * FROM Books<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE CategoryID=p_CatogoryID;<br>END GetCategoryBooks;</p>
<p>(3).NET 程序中：</p>
<p>OracleParameters parameters = {<br>&nbsp;&nbsp;&nbsp;&nbsp; new OracleParameter("p_CURSOR", OracleType.CURSOR, 2000, ParameterDirection.Output, true, 0, 0, "",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataRowVersion.Default, Convert.DBNull),<br>&nbsp;&nbsp;&nbsp;&nbsp; new OracleParameter("p_CatogoryID", OracleType.Int32)<br>};<br><br>parameters[1].Value = 22;<br><br>OracleConnection connection = new OracleConnection( ConnectionString );<br>OracleCommand command = new OracleCommand("GetCategoryBooks", connection);<br>command.CommandType = CommandType.StoredProcedure;<br><br>foreach(OracleParameter parameter in parameters)<br>&nbsp;&nbsp;&nbsp;&nbsp; command.Parameters.Add( parameter );<br><br>connection.Open();<br>OracleDataReader dr = command.ExecuteReader();<br><br>while(dr.Read())<br>{<br>&nbsp;&nbsp;&nbsp; // 你的具体操作。这个就不需要我教吧？<br>}<br>connection.Close();</p>
<p>另外有一点需要指出的是，如果使用 DataReader 取得了一个记录集，那么在 DataReader 关闭之前，程序无法访问输出参数和返回值的数据。</p>
<p>&nbsp;</p>
<p>好了，先这些，总之 .NET 访问 Oracle 还是有很多地方和 SQL Server 不同的，慢慢学习了。</p>
<img src ="http://www.cnitblog.com/salemsu/aggbug/46877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-18 13:36 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/18/46877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQLServer事务与另一个进程已被死锁</title><link>http://www.cnitblog.com/salemsu/archive/2008/07/15/46767.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Tue, 15 Jul 2008 15:57:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/15/46767.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/46767.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/15/46767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/46767.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/46767.html</trackback:ping><description><![CDATA[<p>MS的说明：<br>错误 1205<br>严重级别 13<br>消息正文<br>事务（进程 ID %1!）与另一个进程已被死锁在资源 {%2!} 上，且该事务已被选作死锁牺牲品。请重新运行该事务。<br>解释<br>当 Microsoft? SQL Server? 遇到死锁时发生该错误。当两个（或多个）进程试图访问某个资源，而该资源上有另一个进程控制的锁时，发生死锁。因为每个进程都有对另一个资源的请求，所以各进程都不能完成。当检测到死锁时，SQL Server 将处理时间最少的命令回滚，并向客户端应用程序返回错误信息 1205。该错误不是严重错误，且不会导致批处理终止。<br>对策<br>在某些情况下，死锁条件将导致 DB-Library 函数（如 dbsqlexec、dbsqlok、dbresults 或 dbnextrow）返回 FAIL。程序应该始终检查从每个 DB-Library 函数返回的代码。如果这些 DB-Library 函数之一返回 FAIL，则程序应取消批处理并停止运行。在某些情况下，继续执行批处理中的后续函数是有可能的。但是，因为发生了死锁情况并且回滚了引起死锁的函数，所以批处理中的后续函数将可能因更严重的错误（如"没有找到对象"）而失败。<br>在其它情况下，死锁条件不会导致 DB-Library 函数返回 FAIL。在这些情况下，程序必须在消息处理程序中检查是否有错误信息 1205，并使用 dbsetuserdata 函数将此信息告知应用程序。然后程序必须在每个 DB-Library 调用之后检查是否有死锁指示符，如果检测到死锁则应取消批处理。<br>尽管在收到 1205 死锁消息后取消批处理可能似乎没有必要，但因为服务器并不总是终止死锁情况下的批处理，所以这确实必要。如果未取消批处理，则任何时候试图提交新的批处理时均将导致 DB-Library 错误 10038"结果挂起"。<br>还可以使用 SET DEADLOCK＿PRIORITY 语句（LOW 或 NORMAL）。SET DEADLOCK＿PRIORITY 控制在发生死锁情况时会话的反应方式。如果设置为 LOW，则进程将成为死锁情况下的首选牺牲品。如果设置为 NORMAL，则会话将使用默认的死锁处理方法。<br>如果死锁情况持续，则使用跟踪标记 1204 收集更多信息通常很有用。跟踪标记 1204 打印死锁链和牺牲品，如以下示例输出所示：<br>*** Deadlock Detected ***<br>==&gt; Process 7 chosen as deadlock victim<br>== Deadlock Detected at: 1998-09-10 16:39:29.17<br>== Session participant information:<br>SPID: 7 ECID: 0 Statement Type: UPDATE<br>Input Buf: update t1 set c1 = c1&nbsp; where&nbsp; c1 = 2<br>SPID: 8 ECID: 0 Statement Type: UPDATE<br>Input Buf: update t1 set c1 = c1&nbsp; where&nbsp; c1 = 1</p>
<p>== Deadlock Lock participant information:<br>== Lock: KEY: 2:117575457:1 (010001000000)<br>Database: tempdb<br>Table: t1<br>Index: i1<br>&nbsp;- Held by: SPID 7 ECID 0 Mode "S"<br>&nbsp;- Requested by: SPID 8 ECID 0 Mode "X"<br>== Lock: KEY: 2:117575457:1 (020002000000)<br>Database: tempdb<br>Table: t1<br>Index: i1<br>&nbsp;- Held by: SPID 8 ECID 0 Mode "S"<br>&nbsp;- Requested by: SPID 7 ECID 0 Mode "X"<br>此死锁信息可以解释如下： <br>第一部分显示死锁牺牲品、死锁时间以及死锁中涉及的会话。对于每个会话，显示当前的 SPID、语句类型和输入缓冲区的一部分。<br>第二部分显示有关死锁中涉及的锁的详细信息。从上面的输出，注意死锁涉及表 t1（索引 i1）上的键锁。死锁输出显示哪些进程拥有死锁中涉及的锁，哪些会话在等待锁被授权以及相关联的锁模式。<br>根据默认，生成最小日志量的进程将选作死锁牺牲品，并自动回滚。若要影响所回滚的会话，请为会话设置 DEADLOCK＿PRIORITY。<br>出现这个问题首先要考虑数据库设计的问题，检查会不会由于循环锁引起死锁的问题，即关系互相依赖；第二就要检查程序的问题，作为数据库sa我认为应该从这三方面来检查问题。<br>1、执行：</p>
<p>dbcc traceon (1204, 3605, -1)<br>go<br>dbcc tracestatus(-1)<br>go</p>
<p>目的是把锁信息写到日志上（../log/Errlog)文件上，以检查分析锁的产生；<br>注：　有关DBCC的介绍我会另外写一篇文章介绍 <br>2、设置lock_timeout变量的时间 <br>select @@lock_timeout (查询当前设置）<br>set lock_timeout 1800 (设置当前会话的当前锁超时设置，单位为毫秒）<br>这个应该和程序开发人员商量，嵌入在程序里。　（未做过，待测试：））<br>3、设置DEADLOCK_PRIORITY变量 <br>控制在发生死锁情况时会话的反应方式。具体请查看联机文档。 </p>
<img src ="http://www.cnitblog.com/salemsu/aggbug/46767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-15 23:57 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/15/46767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用存储过程复制表结构</title><link>http://www.cnitblog.com/salemsu/archive/2008/07/10/46547.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Thu, 10 Jul 2008 03:48:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/10/46547.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/46547.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/10/46547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/46547.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/46547.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[P_CopyDB]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)drop procedure [dbo].[P_CopyDB]GO/*-- 在SQLServer 中使用SQLDMO.Transfer...&nbsp;&nbsp;<a href='http://www.cnitblog.com/salemsu/archive/2008/07/10/46547.html'>阅读全文</a><img src ="http://www.cnitblog.com/salemsu/aggbug/46547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-10 11:48 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/10/46547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>缩小SQLSERVER日志文件</title><link>http://www.cnitblog.com/salemsu/archive/2008/07/10/46546.html</link><dc:creator>沙龙</dc:creator><author>沙龙</author><pubDate>Thu, 10 Jul 2008 03:40:00 GMT</pubDate><guid>http://www.cnitblog.com/salemsu/archive/2008/07/10/46546.html</guid><wfw:comment>http://www.cnitblog.com/salemsu/comments/46546.html</wfw:comment><comments>http://www.cnitblog.com/salemsu/archive/2008/07/10/46546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/salemsu/comments/commentRss/46546.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/salemsu/services/trackbacks/46546.html</trackback:ping><description><![CDATA[SET NOCOUNT ON<br id=q3:c goog_docs_charIndex="15">DECLARE @LogicalFileName sysname,<br id=q3:c0 goog_docs_charIndex="49">@MaxMinutes INT,<br id=q3:c1 goog_docs_charIndex="66">@NewSize INT<br id=q3:c2 goog_docs_charIndex="79"><br id=q3:c3 goog_docs_charIndex="80"><br id=q3:c4 goog_docs_charIndex="81">USE Marias -- 要操作的数据库名<br id=q3:c5 goog_docs_charIndex="104">SELECT @LogicalFileName = 'emms_log', -- 日志文件名<br id=q3:c6 goog_docs_charIndex="151">@MaxMinutes = 10, -- Limit on time allowed to wrap log.<br id=q3:c7 goog_docs_charIndex="207">@NewSize = 1 -- 你想设定的日志文件的大小(M)<br id=q3:c8 goog_docs_charIndex="239"><br id=q3:c9 goog_docs_charIndex="240">-- Setup / initialize<br id=q3:c10 goog_docs_charIndex="262">DECLARE @OriginalSize int<br id=q3:c11 goog_docs_charIndex="288">SELECT @OriginalSize = size <br id=q3:c12 goog_docs_charIndex="317">FROM sysfiles<br id=q3:c13 goog_docs_charIndex="331">WHERE name = @LogicalFileName<br id=q3:c14 goog_docs_charIndex="361">SELECT 'Original Size of ' + db_name() + ' LOG is ' + <br id=q3:c15 goog_docs_charIndex="416">CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + <br id=q3:c16 goog_docs_charIndex="472">CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'<br id=q3:c17 goog_docs_charIndex="523">FROM sysfiles<br id=q3:c18 goog_docs_charIndex="537">WHERE name = @LogicalFileName<br id=q3:c19 goog_docs_charIndex="567">CREATE TABLE DummyTrans<br id=q3:c20 goog_docs_charIndex="591">(DummyColumn char (8000) not null)<br id=q3:c21 goog_docs_charIndex="626"><br id=q3:c22 goog_docs_charIndex="627"><br id=q3:c23 goog_docs_charIndex="628">DECLARE @Counter INT,<br id=q3:c24 goog_docs_charIndex="650">@StartTime DATETIME,<br id=q3:c25 goog_docs_charIndex="671">@TruncLog VARCHAR(255)<br id=q3:c26 goog_docs_charIndex="694">SELECT @StartTime = GETDATE(),<br id=q3:c27 goog_docs_charIndex="725">@TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'<br id=q3:c28 goog_docs_charIndex="787"><br id=q3:c29 goog_docs_charIndex="788">DBCC SHRINKFILE (@LogicalFileName, @NewSize)<br id=q3:c30 goog_docs_charIndex="833">EXEC (@TruncLog)<br id=q3:c31 goog_docs_charIndex="850">-- Wrap the log if necessary.<br id=q3:c32 goog_docs_charIndex="880">WHILE @MaxMinutes &gt; DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired<br id=q3:c33 goog_docs_charIndex="961">AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) <br id=q3:c34 goog_docs_charIndex="1040">AND (@OriginalSize * 8 /1024) &gt; @NewSize <br id=q3:c35 goog_docs_charIndex="1082">BEGIN -- Outer loop.<br id=q3:c36 goog_docs_charIndex="1103">SELECT @Counter = 0<br id=q3:c37 goog_docs_charIndex="1123">WHILE ((@Counter &lt; @OriginalSize / 16) AND (@Counter &lt; 50000))<br id=q3:c38 goog_docs_charIndex="1186">BEGIN -- update<br id=q3:c39 goog_docs_charIndex="1202">INSERT DummyTrans VALUES ('Fill Log') <br id=q3:c40 goog_docs_charIndex="1241">DELETE DummyTrans<br id=q3:c41 goog_docs_charIndex="1259">SELECT @Counter = @Counter + 1<br id=q3:c42 goog_docs_charIndex="1290">END <br id=q3:c43 goog_docs_charIndex="1295">EXEC (@TruncLog) <br id=q3:c44 goog_docs_charIndex="1313">END <br id=q3:c45 goog_docs_charIndex="1318">SELECT 'Final Size of ' + db_name() + ' LOG is ' +<br id=q3:c46 goog_docs_charIndex="1369">CONVERT(VARCHAR(30),size) + ' 8K pages or ' + <br id=q3:c47 goog_docs_charIndex="1416">CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'<br id=q3:c48 goog_docs_charIndex="1458">FROM sysfiles <br id=q3:c49 goog_docs_charIndex="1473">WHERE name = @LogicalFileName<br id=q3:c50 goog_docs_charIndex="1503">DROP TABLE DummyTrans<br id=q3:c51 goog_docs_charIndex="1525">SET NOCOUNT OFF <br id=q3:c52 goog_docs_charIndex="1542">
<img src ="http://www.cnitblog.com/salemsu/aggbug/46546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/salemsu/" target="_blank">沙龙</a> 2008-07-10 11:40 <a href="http://www.cnitblog.com/salemsu/archive/2008/07/10/46546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>