2016-10-29 56 views
2

我有可運行的代碼,下面只是打印消息,並且對我很感興趣。我沒有任何其他與此表相關的觸發器(我做了一個下拉表來強化它),但是當第一次觸發複合觸發器(首次插入表格)時,會發生以下行爲:複合觸發器在第一次插入時的行爲與第一次插入時的行爲不同

  • 試驗1)的BEFORE語句運行兩次第一插入但只是一次之後

BEFORE語句數量:0 BEFORE語句數量:0

  • 測試2)變量qty對於第一次插入具有NULL值,之後具有期望值。

語句後數量:

你可以解釋這種現象?


SET SERVEROUTPUT ON;  
--DROP TABLE teste_var_global; 

CREATE TABLE teste_var_global(
    idVal NUMBER 
); 


create or replace TRIGGER compounder 
FOR UPDATE OR INSERT OR DELETE ON teste_var_global 
COMPOUND TRIGGER 

    qty NUMBER; 

    BEFORE STATEMENT IS 
     BEGIN 
     SELECT COUNT(*) INTO qty FROM teste_var_global; 
     DBMS_OUTPUT.PUT_LINE('BEFORE STATEMENT IS'); 
     DBMS_OUTPUT.PUT_LINE('Qty: ' || qty); 
    EXCEPTION 
     WHEN OTHERS THEN 
     DBMS_OUTPUT.PUT_LINE('(' || SQLCODE || ') - ' || SQLERRM); 
    END BEFORE STATEMENT; 

    BEFORE EACH ROW IS 
    BEGIN 
     DBMS_OUTPUT.PUT_LINE(CHR(9)||'BEFORE EACH ROW IS'); 
     IF INSERTING THEN 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal); 
     ELSIF DELETING THEN 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal); 
     ELSE --UPDATING 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal); 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal); 
     END IF; 
    END BEFORE EACH ROW; 

    AFTER EACH ROW IS 
    BEGIN 
     DBMS_OUTPUT.PUT_LINE(CHR(9)||'AFTER EACH ROW IS'); 
     IF INSERTING THEN 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal); 
      DBMS_OUTPUT.NEW_LINE(); 
      qty:= qty + 1; -- increment 
     ELSIF DELETING THEN 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal); 
      DBMS_OUTPUT.NEW_LINE(); 
      qty:= qty -1; -- decrement 
     ELSE --UPDATING 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal); 
      DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal); 
      DBMS_OUTPUT.NEW_LINE(); 
     END IF; 
    END AFTER EACH ROW; 

    AFTER STATEMENT IS 
    BEGIN 
     DBMS_OUTPUT.PUT_LINE('AFTER STATEMENT IS'); 
     DBMS_OUTPUT.PUT_LINE('Qty: ' || qty); 
     DBMS_OUTPUT.NEW_LINE(); 
    END AFTER STATEMENT; 
    END; 
/

-- Test 1, will fire BEFORE STATMENT twice when the first row is inserted 
INSERT INTO teste_var_global 
(
SELECT 1 FROM DUAL 
UNION ALL 
SELECT 2 FROM DUAL 
UNION ALL 
SELECT 3 FROM DUAL 
) 
/

--Test 2, qty will become NULL when this trigger is fired for the first time 
--drop the table and rerun the trigger before executing this command 
INSERT INTO teste_var_global VALUES(1); 
/
+1

因爲Oracle確保觸發器在最後一次**被觸發**,但不能保證它在多用戶環境中被激發**一次**,請參閱此鏈接:https://asktom.oracle .com/pls/asktom/f?p = 100:11:0 :::: P11_QUESTION_ID:2599480800346313755 – krokodilko

+0

@krokodilko這是非常好的解釋。 – Kacper

回答

0

這是怎麼看起來輸出上我的數據庫,當我創建你的表和觸發器。

BEFORE STATEMENT IS 
Qty: 0 
    BEFORE EACH ROW IS 
    :new.idVal 1 
    AFTER EACH ROW IS 
    :new.idVal 1 

    BEFORE EACH ROW IS 
    :new.idVal 2 
    AFTER EACH ROW IS 
    :new.idVal 2 

    BEFORE EACH ROW IS 
    :new.idVal 3 
    AFTER EACH ROW IS 
    :new.idVal 3 

AFTER STATEMENT IS 
Qty: 3 

第二測試情況得出:

BEFORE STATEMENT IS 
Qty: 0 
    BEFORE EACH ROW IS 
    :new.idVal 1 
    AFTER EACH ROW IS 
    :new.idVal 1 

AFTER STATEMENT IS 
Qty: 1 

但是,krokodilko在你的問題下面的評論貼,請參閱鏈接。

相關問題