我有一个数据库,其中包含这两个表:
NARUDZBENICA(**SIFANAR**,DATUM,NAZIV,*SIFRADOB,SIFRAKATALOGA,SIFRAZAP,SIFRANACISP*)
DOBAVLJAC(**SIFRADOB**,NAZIV,MAIL,TELEFON,FAKS)
我需要一个语句触发器来更新表NARUDZBENICA中所有行中的'naziv'列,其中当我在DOBAVLJAC上更改列'naziv'时,SIFRADOB以'0'开头,其中SIFRADOB是主键。
这就是我提出的:
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;
答案 0 :(得分:0)
我不知道你要做什么来禁用并在另一个触发器中启用一个触发器。否则我几乎可以看到你正在尝试做什么,我只是不明白为什么。
用简单的语言:当表DOBAVLJAC中的字段NAZIV更新时,字段的旧值将保存到表NARUDZBENICA中的相同字段,其中字段SIFRADOB以字符' 0'开头。 / p>
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值。如果它仍为null,则表示这是第一个Update,因此将更新发送到另一个表。 该更新将NAZIV值设置为新值,并将标志字段设置为任何非空值。非空值告诉另一个触发器,这是传播更新,因此结束传播。它将:new.flag值更改为null(您实际上从未实际更改表中标志字段的内容)并且只允许更新。这两个表的触发器中的逻辑相同。
使用Oracle 12c和隐藏列可以轻松实现这一点。它只是允许你从正常视图中隐藏标志字段,这样人们就不会总是到处询问它是什么。
在阅读我的描述时,我不认为我明确表达了我的观点,特别是对于非英语母语人士。所以这是触发器代码:
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;
这不是生产级编码,但我希望它能说明这个想法。
答案 1 :(得分:0)
:new
或:old
个标识符只能在row-level
个触发器中使用。对于statement level
触发器,禁止使用:new
和:old
标识符。
此外,您无法在触发器中commit
。因此,您需要执行任何使用autonomous
事务所需的DML操作。请参阅下文,了解如何做到这一点。
对于表ID
中A_TABLE
列值的任何更改,都会触发此触发器。
新值将被捕获并传递给匿名交易。
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;