Posted on 2009-02-17 18:50
大大毛 閱讀(468)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
VB
使用ADO時(shí)經(jīng)常都會(huì)遇到要利用事務(wù)批次提交SQL的情況,如果使用不當(dāng)?shù)奶峤环绞綍?huì)出現(xiàn)預(yù)料外的問(wèn)題,現(xiàn)在先看下面的示例代碼:
?1?Private?Sub?cmdRun_Click()
?2?On?Error?GoTo?ErrHandle
?3?????Dim?con?As?Connection
?4?????Dim?strSQL?As?String
?5?????strSQL?=?""
?6?????'第一筆SQL1
?7?????strSQL?=?strSQL?&?"Insert?Into?tb1?Values?(...)"?&?vbNewLine
?8?????'第二筆SQL2
?9?????strSQL?=?strSQL?&?"Update?tb1?Set?C=1?Where?..."?&?vbNewLine
10?????'...
11?????'第N筆SQLn
12?????strSQL?=?strSQL?&?"Delete?tb1?Where?..."?&?vbNewLine
13?????Set?con?=?getCon()??'獲取/打開(kāi)DB連線
14?????'準(zhǔn)備事務(wù)
15?????con.BeginTrans
16?????'一批一起執(zhí)行
17?????con.Execute?strSQL
18?????'提交事務(wù)
19?????con.CommitTrans
20?ExitHandle:
21?????If?con.State?=?1?Then?con.Close
22?????Set?con?=?Nothing
23?????Exit?Function
24?ErrHandle:
25?????con.RollbackTrans
26?????GoTo?ExitHandle
27?????MsgBox?Err.Description
28?End?Sub
???上面這段程式利用換行符(分號(hào)也可)來(lái)將多條SQL合成一個(gè)字符串,最後在事務(wù)中執(zhí)行一次就OK,既簡(jiǎn)潔又漂亮的想法。
???看似OK,但實(shí)際卻是埋下了禍端。從事務(wù)的機(jī)制來(lái)看,在事務(wù)中提交的SQL應(yīng)該是一起成功/失敗的,而且這裏也有利用異常捕獲機(jī)制來(lái)實(shí)現(xiàn)RollBack,那麼在使用時(shí)到底是會(huì)出現(xiàn)什麼情況呢?
???(0) SQL1,SQL2,...SQLn其中有語(yǔ)句含有非執(zhí)行時(shí)的語(yǔ)法錯(cuò)誤,比如說(shuō)嵌套語(yǔ)句少掉一個(gè)右括號(hào)等;
??????OK。這種情況下,可以發(fā)現(xiàn)執(zhí)行結(jié)果如預(yù)期,SQL1 -> SQLn都不會(huì)被執(zhí)行,且會(huì)提示錯(cuò)誤訊息。
???(1) SQL1,SQL2,...SQLn都執(zhí)行成功;
??????OK。這種情況下,可以發(fā)現(xiàn)執(zhí)行結(jié)果如預(yù)期,SQL1 -> SQLn都會(huì)被執(zhí)行,可以正確提交事務(wù)。
???(2) SQL1,SQL2,...SQLn其中有語(yǔ)句會(huì)執(zhí)行失敗;
??????(2.1) SQL1可以執(zhí)行,而SQL2會(huì)發(fā)生執(zhí)行時(shí)期錯(cuò)誤(比如UPDATE上去欄位超過(guò)寬度);
?????????NO。Execute執(zhí)行成功,查詢(xún)結(jié)果會(huì)發(fā)現(xiàn)SQL1的結(jié)果有提交,而SQL2以及之後的SQL都沒(méi)有執(zhí)行。
??????(2.2) SQL1會(huì)發(fā)生執(zhí)行時(shí)期錯(cuò)誤(比如UPDATE上去欄位超過(guò)寬度),而SQL2及其後的SQL可以被執(zhí)行;
?????????OK。這種情況下,可以發(fā)現(xiàn)有提示錯(cuò)誤訊息,事務(wù)會(huì)被RollBack,SQL1 -> SQLn都不會(huì)被執(zhí)行。
???通過(guò)上面的幾種情況可以得到結(jié)論,如果是以一整個(gè)字串(中間用換行或分號(hào)分隔)來(lái)提交多筆SQL命令時(shí),在所有SQL語(yǔ)法檢查OK後,執(zhí)行的成功與否取決於第1筆SQL的執(zhí)行狀態(tài),因此就是說(shuō)如果第一筆SQL執(zhí)行OK,那麼該事務(wù)就一定會(huì)被Commit。
???所以說(shuō),在使用事務(wù)提交多筆SQL時(shí)不能使用上面的提交方式,而必須逐筆的提交才行。