[英]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_TABLE
中ID
列值的任何更改將觸發此觸發器。 新值將被捕獲並傳遞給匿名事務。
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.