簡體   English   中英

PL SQL中與更新相關的表列上的更新表列

[英]Update table column on update related table column in pl sql

我有一個數據庫,其中包含以下兩個表:

NARUDZBENICA(**SIFANAR**,DATUM,NAZIV,*SIFRADOB,SIFRAKATALOGA,SIFRAZAP,SIFRANACISP*)
DOBAVLJAC(**SIFRADOB**,NAZIV,MAIL,TELEFON,FAKS)

我需要一個語句觸發器來更新表NARUDZBENICA的所有行中的列“ naziv”,當我更改DOBAVLJAC上的列“ naziv”(其中SIFRADOB是主鍵)時,SIFRADOB以“ 0”開頭。

這是我想出的:

CREATE OR REPLACE TRIGGER "STATEMENT_DOB" 
AFTER UPDATE OF NAZIV ON DOBAVLJAC 
BEGIN
    EXECUTE IMMEDIATE 'ALTER TRIGGER UPDATE_NAR_FRB DISABLE';
    UPDATE NARUDZBENICA
    SET NAZIV = (SELECT :OLD.NAZIV FROM DOBAVLJAC)
    WHERE ROWNUM > 1 AND SIFRADOB = '%0';   
    EXECUTE IMMEDIATE 'ALTER TRIGGER UPDATE_NAR_FRB ENABLE';          
END;

我不知道您要嘗試在另一個觸發器中禁用和啟用觸發器。 否則,我幾乎可以看到您正在嘗試做什么,我只是不明白為什么。

用簡單的語言:更新表DOBAVLJAC中的字段NAZIV時,該字段的舊值將保存到表NARUDZBENICA中的同一字段中,其中SIFRADOB字段以字符“ 0”開頭。

create or replace trigger STATEMENT_DOB
after update of NAZIV on DOBAVLJAC
begin
    update  NARUDZBENICA
        set NAZIV = :old.NAZIV
    where   SIFRADOB like '0%';
end;

我剛剛想到了為什么您可能要禁用另一個觸發器。 它是另一張表上的更新觸發器,該表監視同一字段,從而將更改傳播到DOBAVLJAC。 這將導致無休止的更新循環。 (這也意味着您可能應該使用:new.NAZIV值而不是:old.NAZIV。)

有幾種技巧可以解決該問題。 涉及更多的是重命名兩個表並使用原始表名創建視圖。 每個視圖上的“代替”觸發器將更新兩個表的NAZIV更改。 沒有循環。

這是一個相當復雜的解決方案。 一個簡單的方法(涉及較少的對象更改)是在兩個表中都創建一個標志列。 該列的值始終為NULL。 執行觸發器時(必須是before觸發器),它將檢查標志列的NEW值。 如果仍然為空,則表示這是第一個Update,因此將更新發送到另一個表。 更新將NAZIV值設置為新值並將標志字段設置為任何非空值。 非null值告訴另一個觸發器這是傳播更新,因此結束傳播。 它將:new.flag值更改為null(您實際上從未更改過表中flag字段的內容),僅允許更新。 這兩個表上的觸發器中的邏輯相同。

Oracle 12c和不可見列使此操作變得更加容易。 它僅允許您從常規視圖中隱藏flag字段,因此人們不必總是四處尋找它的用途。

在閱讀我的描述時,我認為我沒有清楚地表達我的觀點,特別是對於非英語母語者。 因此,這是觸發代碼:

create or replace trigger STATEMENT_DOB -- UPDATE_NAR_FRB
before update of NAZIV, Flag on DOBAVLJAC -- NARUDZBENICA
begin
    if updating( Flag ) and not updating( NAZIV ) then
        -- Someone playing around updating Flag only. Don't allow.
        :new.FLAG := null;
    elsif :new.FLAG is null then
        -- Original Update. Propagate to other table
        update  NARUDZBENICA -- DOBAVLJAC
            set NAZIV = :new.NAZIV,
                Flag  = 1
        where   SIFRADOB like '0%';
    else
        -- This was propagation from other table. Just allow the update of NAZIV
        -- but first reset the flag...
        :new.FLAG := null;
    end if;
end;

那不是完全的生產級編碼,但是我希望它能說明這個想法。

:new:old標識符只能row-level觸發器中使用。 對於statement level觸發器,禁止使用:new:old標識符。 同樣,您不能commit觸發器。 因此,如果您想執行任何DML操作,則需要使用autonomous事務。 參見下文如何操作。

A_TABLEID列值的任何更改將觸發此觸發器。 新值將被捕獲並傳遞給匿名事務。

CREATE OR REPLACE TRIGGER STATEMENT_DOB 
AFTER UPDATE OF ID ON A_TABLE 
for each row
BEGIN

 proc_upd_tb(:new.id); 

END;

自主交易:

數據可以在這里更新並提交,如圖所示。

create or replace procedure proc_upd_tb(id number)
as 
PRAGMA AUTONOMOUS_TRANSACTION;
begin

   UPDATE AA
    SET A = id;
    where <condition> ;
    commit;

end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM