原來調用存儲過程的地方都沒有使用事務,當然裡面包括多個表的更新操作,使用都很正常。後來我給加上了jdbc事務,代碼如下:
引用:
TransactionStatus status = super.beginTransaction();
try {
map = getFtglUtils().cancelFtrw(getPageAjlb(),
key.getId1().intValue(), key.getId2().intValue(), qxyy,
iState);
super.getTransactionManager().commit(status);
} catch (Exception e) {
super.getTransactionManager().rollback(status);
throw new SystemException(e);
}
加上事務之後就發現存儲過程沒有完全執行,裡面的update語句都沒有執行,但是最後的select還能返回結果集,調用後台也不報錯……百思不得其解。後來湊巧把存儲過程中創建臨時表的如下語句:
引用:
-- 創建臨時表
create table #tmpBAGL
(
BH int, -- 編號
RWXH smallint -- 任務序號
)
移到了使用這個臨時表的if else裡面,因為只有在一定的條件下才需要創建臨時表。再試了一下調用存儲過程,發現一切正常了!這一次存儲過程沒有執行創建臨時表,就正常了……遂上網搜到一個如下的描述:
引用:
select into可以在事務中使用,但是前提條件是這個事務只有select into一條語句。
SELECT INTO command not allowed within multi-statement transaction.
注意是multi-statement transaction
大家都知道,select into #tabel的最大優勢是速度快,但這個速度快是用不記錄日志來實現的。
而使用事務的目的就是要麼事務中的所有操作全部執行,要麼所有操作全部回滾。
這是靠日志中記錄的操作來保證的。
如果select into可以在多語句的事務中使用,但是它本身又是不計日志的,也就是不能回滾的。
這就和事務的定義矛盾了。
因此,select into不能在多語句的事務中使用。
但也不是說我們不能使用select into這個好東東,set chained off,使用非鏈式事務或者把select into
放在單獨一個事務中運行就可以了。
還有一個在多語句事務中被禁止的,而在應用中會常需要的命令是truncate table。
原因和解決方法也如上所說。
把存儲過程還原成最開始那樣,在創建臨時表之前加上set chained off,再次運行問題解決