台灣最大程式設計社群網站
線上人數
776
 
會員總數:242469
討論主題:187511
歡迎您免費加入會員
討論區列表 >> Blog精華文章 >> Oracle "pragma autonomous_transaction" CASE
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
Oracle "pragma autonomous_transaction" CASE
價值 : 0 QP  點閱數:678 回應數:0

樓主

花旗蔘 版主
高級專家
10938 129
4285 516
發送站內信

Q:

請教一下各位大大 我有兩個table
/*
create table COPLIST
(單別 VARCHAR2(10),
單號 VARCHAR2(11),
序號 VARCHAR2(4),
品號 VARCHAR2(10),
數量 NUMBER(18,0),
客戶 VARCHAR2(10))


create table logbb
(cc varchar(100));
*/

我在上面寫了一個trigger 編譯沒有錯誤訊息 但執行後卻不行
/*
CREATE OR REPLACE TRIGGER coptrig AFTER UPDATE ON coplist
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
CURSOR cr IS
SELECT "序號","品號","數量","客戶" FROM coplist where "單別"= :new."單別" and "單號"= :new."單號";

BEGIN

FOR crx IN cr LOOP

INSERT INTO logbb(cc)VALUES(crx."序號");

END LOOP;
END;
*/

INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0001');
INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0002');
INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0003');

update coplist set "數量"='100' where "單號"='0318'
會出現
SQL 錯誤: ORA-04091: 表格 SYSTEM.COPLIST 正在變更中, 觸發程式/函數無法檢視它
ORA-06512: 在 "SYSTEM.COPTRIG", line 3
ORA-06512: 在 "SYSTEM.COPTRIG", line 7
ORA-04088: 執行觸發程式 'SYSTEM.COPTRIG' 時發生錯誤
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.

A:

整段看下來你最近問的這兩個問題 核心都在 ORA-4091
其實我在你 "trigger + cursor問題"中的 #4
有提示過你了,
maybe you can try
"pragma autonomous_transaction"
google it for detail info.

你的business model 我不了解,總之就你的ISSUE來說
如果你要使用 你習慣的寫法 就是cursor那個
可使用 例1
1'使用pragma autonomous_transaction
EX:
CREATE OR REPLACE TRIGGER coptrig
AFTER UPDATE ON cops
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
declare
CURSOR cr IS
SELECT "TA003","TA004","TA005","TA006" FROM COPS where "TA001"= :NEW."TA001" AND "TA002"= :NEW."TA002";
pragma autonomous_transaction; --*
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc)VALUES(crx."TA003");
commit; --*
END LOOP;
END;

注意 * 號部份.
另外 pragma autonomous_transaction的用法是 所謂的自主交易
也就是說你的 update 跟 trigger 所觸發的dml 是各自的兩個transaction
結論就是
A tx:update 資料 -->B tx :trigger 觸發 dml
今天即使A tx 被rollback了,B tx 不會連帶被rollback了.

2'我不清楚你的business model,但若針對 你問題的陳述來看,
提供個意見就是改用before update 的trigger,你可評估符合你需求否?

這樣寫 兩者納為一個transaction 處理

ex:
CREATE OR REPLACE TRIGGER coptrig
before UPDATE ON cops
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
INSERT INTO logbb(cc)VALUES(:new."TA003");
END;
 


本篇文章發表於2013-03-21 12:29
== 簽名檔 ==
Oracle/EBS/MS SQL DBA
--My BLOG
http://itgroup.blueshop.com.tw/benchenBEN/blog
別忘捐VP感謝幫助你的人 新手會員瞧一瞧
目前尚無任何回覆
   

回覆
如要回應,請先登入.