<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    java思維

    正在學習中:(

    Oracle 的Trigger 中不能操作基表(轉)

    在將SYBASE的Trigger移植到ORACLE的時候發現一個問題,

    就是在一張表的Trigger中不能含有操作該基表的SQL,

    例如STOCKINFO的Trigger里不有操作STOCKINFO的SQL。

    那加權平均價如何取呢?

    現在只能在原平均價的基礎再與新價進行加權平均,結果是一樣的。

    注意:

    AFTER UPDATE的Trigger不能操作基表,只有在BEFORE INSERT的Trigger里才能操作基表。

    BEFORE INSERT的Trigger只有用INSERT INTO T1(COL1) VALUES('1');才有效,

    INSERT INTO T1(COL1) SELECT '1' FROM DUAL;也是無效的。

    例如:

    SQL> insert into t1 values (1,'a'); --先插入一條數據,避免ORA-01403: no data found 錯誤。
    1 row inserted
    SQL> commit;

    SQL> create or replace trigger tri_t1
    2 before insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1;
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (2,'b'); -- insert into ... values 沒有問題
    1 row inserted

    SQL> insert into t1 select '3','c' from dual; -- insert into ... select .. from 報錯
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

     并且:old和:new只有在行級(for each row)的Trigger有效。

    網上原文:

    ORA-04091與 table mutating

    近日解決了一個trigger中報ORA-04091錯誤的問題,補了關于Oracle table mutating的一課:

    mutating table 是指一個當前正在被update,delete,insert語句修改的表,如果在一個行級別的trigger中讀取或修改一個mutating table,則往往會遇到ORA-04091錯誤.例如,如果在trigger中使用了select或dml 語句訪問trigger所在的表,則就會收到這個錯誤。

    然而,Oracle8i和9i文檔中都沒有解釋清楚before和after 類型的 row trigger 在對待兩種不同的insert語句(insert into ... values ... 與 insert into ... select ...)時的差別:

    1、對于after 類型的 for each row 級別的triggers,不論哪種insert語句觸發了trigger,都不允許在 trigger 中訪問本trigger所依賴的table的,測試如下:
    SQL> create table t1 ( c1 number,c2 varchar2(10));
    Table created
    SQL> create or replace trigger tri_t1
    2 after insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1; --這里訪問了trigger 本表
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (1,'a');
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TES.TRI_T1'

    SQL> insert into t1 select '1','a' from dual;
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

    2、對于before 類型的 for each row 級別的triggers,如果使用 insert into ... values 語句觸發此trigger ,則在trigger 中訪問本table沒有問題;
    但如果使用 insert into select .. from 語句觸發此trigger ,則在trigger 中訪問本table就報ora-04091錯誤;
    只有在Oracle 7標準的開發文檔中有這樣的說明:
    From the Application Developers Guide
    "There is an exception to this restriction;
    For single row INSERTs, constraining tables are mutating for
    AFTER row triggers, but not for BEFORE row triggers.
    INSERT statements that involve more than 1 row are not considered
    single row inserts."
    "INSERT INTO <table_name> SELECT ..." are not considered single row
    inserts, even if they only result in 1 row being inserted.

    測試如下:
    SQL> drop trigger tri_t1;
    Trigger dropped

    SQL> insert into t1 values (1,'a'); --先插入一條數據,避免ORA-01403: no data found 錯誤。
    1 row inserted
    SQL> commit;

    SQL> create or replace trigger tri_t1
    2 before insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1;
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (2,'b'); -- insert into ... values 沒有問題
    1 row inserted

    SQL> insert into t1 select '3','c' from dual; -- insert into ... select .. from 報錯
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

    我們的開發人員因為不知道這個特別情況,近日在修改一個存儲過程時候,將原來的insert values 寫法改成了insert select 寫法,而trigger 又是before類型的,導致出現了ORA-04091錯誤,搞得分析了好久也沒有頭緒。

    其實,在metalink中有一篇note說到了:

    文檔 ID: 注釋:132569.1
    主題: ORA-4091 on BEFORE ROW TRIGGER with INSERT statement
    類型: PROBLEM
    狀態: PUBLISHED
    內容類型: TEXT/X-HTML
    創建日期: 16-JAN-2001
    上次修訂日期: 09-AUG-2004

    Problem Description
    -------------------

    You want to do an insert into a table that has a BEFORE row Trigger.

    When you hard code the values into the INSERT statement, the trigger works fine.

    For example:

    INSERT
    INTO content (cont_name,cont_seg,cat_seq)
    VALUES('blah',100,200);

    1 row created.

    However, your trigger errors with ERROR ORA-4091 with
    INSERT INTO...select statement:

    INSERT
    INTO content (cont_name,cont_seq,cat_seq) (select....from category);

    ERROR at line 1:
    ORA-4091: table <schema>.CONTENT is mutating, trigger/function may not see it
    ORA-6512: at "<schema>.INS_CONTENT", line 4
    ORA-4088: error during execution of trigger '<schema>.INS_CONTENT'


    TRIGGER:

    CREATE OR REPLACE trigger INS_CONTENT
    BEFORE INSERT on CONTENT
    FOR EACH ROW
    DECLARE
    max_sort number;
    BEGIN
    SELECT max(cont_sort) INTO max_sort FROM CONTENT;
    IF max_sort IS NOT NULL AND max_sort!= 99999 THEN
    IF :new.cont_sort IS NULL THEN
    :new.cont_sort := max_sort +1;
    END IF;
    END IF;
    SELECT SEQ_CONT_SEQ.nextval INTO :new.CONT_SEQ from dual;
    END;


    Explanation
    -----------

    Error: ORA 4091
    Text: table %s.%s is mutating, trigger/function may not see it
    -------------------------------------------------------------------------------
    Cause: A trigger (or a user defined PL/SQL 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.

    Explanation:
    You cannot look at or modify the table that is mutating.

    Note:
    From the Application Developers Guide
    "There is an exception to this restriction;
    For single row INSERTs, constraining tables are mutating for
    AFTER row triggers, but not for BEFORE row triggers.
    INSERT statements that involve more than 1 row are not considered
    single row inserts."

    "INSERT INTO <table_name> SELECT ..." are not considered single row
    inserts, even if they only result in 1 row being inserted.


    RELATED DOCUMENTS
    -----------------

    Oracle Application Developer's Guide (A68003-01)
    Chapter 'Using Database Triggers', page 13-22)

    posted on 2007-04-27 22:36 john 閱讀(4336) 評論(3)  編輯  收藏 所屬分類: Oracle Technology

    評論

    # re: Oracle 的Trigger 中不能操作基表(轉) 2008-03-21 11:57 分享愛的空間

    對于before 類型的 for each row 級別的triggers,在trigger中,對基表進行修改操作好像也會出同樣的錯,看來操作僅限于查詢語句。  回復  更多評論   

    # re: Oracle 的Trigger 中不能操作基表(轉) 2008-03-21 14:21 分享愛的空間

    剛才我試了在before觸發器中用本表,哪怕是簡單的查詢好像也不管用。
    是我的oracle的版本問題嗎?
    我用的是Oracle9i Enterprise Edition Release 9.2.0.4.0
    你的例子中使用本表,是不是用的一種很特殊的方式。  回復  更多評論   

    # re: Oracle 的Trigger 中不能操作基表(轉)[未登錄] 2008-11-07 11:35 凌寒

    遇到修改刪除時不能操縱基表的問題了,怎么解決呢?
    怎么解決呢??
    我現在都是熱鍋上的螞蟻了!  回復  更多評論   

    主站蜘蛛池模板: 久久精品一本到99热免费| 亚洲视频一区调教| 亚洲kkk4444在线观看| 久久久久久毛片免费播放| 亚洲精品电影天堂网| 亚洲一级免费毛片| 亚洲av一本岛在线播放| 毛片a级毛片免费播放100| 亚洲色图激情文学| 国产真实伦在线视频免费观看| 亚洲国产精品ⅴa在线观看| 女人18毛片水真多免费看| 亚洲国产无线乱码在线观看 | 久久电影网午夜鲁丝片免费| 亚洲成人在线免费观看| 免费无码黄十八禁网站在线观看| 亚洲日韩一区二区三区| 国产免费观看a大片的网站| 草久免费在线观看网站| 亚洲人成人无码网www电影首页| 免费一区二区三区| 亚洲成a人片在线看| 免费a级毛片18以上观看精品| yellow免费网站| 亚洲嫩模在线观看| 成人黄动漫画免费网站视频| 国产亚洲精品国产福利在线观看 | 亚洲一区二区电影| 女人18特级一级毛片免费视频| 一级毛片视频免费| 亚洲综合激情另类小说区| 国产无遮挡色视频免费视频| 国产免费人成视频在线播放播| 亚洲午夜精品一区二区| 天天看免费高清影视| 国产一级在线免费观看| 中国china体内裑精亚洲日本| 亚洲免费一区二区| 国产免费AV片在线播放唯爱网| 成年免费大片黄在线观看com| 亚洲午夜精品久久久久久人妖|