更新pl sql中更新相关表列的表列

时间:2015-02-01 21:06:16

标签: oracle plsql oracle11g triggers oracle-sqldeveloper

我有一个数据库,其中包含这两个表:

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;

2 个答案:

答案 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操作。请参阅下文,了解如何做到这一点。

对于表IDA_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;