在复合触发器中声明游标 pl/sql

declaring cursor in compound trigger pl/sql

当我运行这段代码时,我得到了这个错误:
PLS-00103:在期望以下之一时遇到符号 "IS":

   := . ( @ % ; not null range default character.

我认为声明部分有问题,但相同的声明在 row-lvl 触发器中有效,所以我很困惑在复合触发器中是否允许这样做。我找不到例子,所以我在这里问你。

create or replace trigger ivan_moving
  for update of country on clients
    compound trigger 
  declare
  n_country clients.country%type;
  min_date clients.bday%type;
  cursor ivans is select* from clients where fname like 'Ivan%' and Bday > (select min(Bday) from clients where fname like 'Ivan%');
  client_ivan ivans%rowtype;

  before statement is
  min_date = select Bday from clients where fname like 'Ivan%' and Bday = (select min(Bday) from clients where fname like 'Ivan%');
  end before statement;

  after each row is
  begin
   if :OLD.country <> :NEW.country and fname = 'Ivan%' and bday = min_date
    n_country := :new.country;
   end if;
  end after each row;

  after statement is
  begin
  open ivans;
   loop
    fetch ivans into client_ivan; 
    exit when ivans%notfound;
    update clients set country = n_country where id = client_ivan.id;
   end loop;
  close ivans; 
  end after statement;

end ivan_moving;
/

不少错误,例如

  • 你不应该使用 declare
  • 在 PL/SQL 中,SELECT 需要 INTO
  • 不是= 'Ivan%'而是like 'Ivan%'
  • 您似乎"forgot" 为某些列指定了:new

可能还有其他一些我没有提到的错误。我不知道触发器是否按照您的预期执行,但是 - 至少语法错误现在已修复。

SQL> create or replace trigger ivan_moving
  2    for update of country on clients
  3    compound trigger
  4      n_country clients.country%type;
  5      min_date  clients.bday%type;
  6      cursor ivans is
  7        select * from clients
  8          where fname like 'Ivan%'
  9            and bday > min_date;
 10      client_ivan ivans%rowtype;
 11
 12    before statement is
 13      begin
 14        select bday
 15          into min_date
 16          from clients
 17          where fname like 'Ivan%'
 18            and bday = (select min(bday)
 19                        from clients
 20                        where fname like 'Ivan%');
 21      end before statement;
 22
 23    after each row is
 24      begin
 25        if     :old.country <> :new.country
 26           and :new.fname like 'Ivan%'
 27           and :new.bday = min_date
 28        then
 29           n_country := :new.country;
 30        end if;
 31      end after each row;
 32
 33    after statement is
 34      begin
 35        open ivans;
 36        loop
 37          fetch ivans into client_ivan;
 38          exit when ivans%notfound;
 39          update clients set country = n_country where id = client_ivan.id;
 40        end loop;
 41        close ivans;
 42      end after statement;
 43
 44  end ivan_moving;
 45  /

Trigger created.