<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 凌寒

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

    主站蜘蛛池模板: 特级做a爰片毛片免费看| 亚洲人成色777777老人头| 亚洲伊人久久大香线蕉影院| 亚洲一卡二卡三卡| 亚洲精品自偷自拍无码| 老外毛片免费视频播放| 成全高清在线观看免费| 1000部啪啪未满十八勿入免费| 最近免费中文字幕大全| 亚洲日韩在线观看免费视频| 亚洲AV无码AV男人的天堂| 亚洲六月丁香六月婷婷色伊人 | 亚洲午夜精品一区二区| 亚洲天堂男人影院| 乱淫片免费影院观看| 免费人成视频在线观看网站 | **真实毛片免费观看| 色www永久免费视频| 亚洲精品无码久久久久去q | 亚洲综合一区无码精品| 永久免费精品影视网站| 100部毛片免费全部播放完整| 黄网址在线永久免费观看| 亚洲五月综合缴情在线观看| 亚洲人成小说网站色| 精品国产污污免费网站入口| 久久久久久毛片免费播放 | 2019中文字幕免费电影在线播放| 日韩一区二区免费视频| 亚洲国产精品成人精品无码区 | 亚洲日韩中文字幕无码一区| 久久国产精品免费一区| 欧美在线看片A免费观看| 国产午夜亚洲不卡| 久久精品国产亚洲av麻豆蜜芽| 一级大黄美女免费播放| 无码乱肉视频免费大全合集 | 亚洲AV无码乱码在线观看代蜜桃| 成人午夜免费视频| 99久久免费精品国产72精品九九 | 国产亚洲精品精华液|