编写触发器时出现另一个 PLS-00103

Another PLS-00103 when writing a trigger

所以我正在使用 sql 开发人员为数据库编写触发器,但我无法解决这个问题:

这是我的触发器(较短的版本,但我尝试让它工作)

create or replace trigger trig_ognisko
        before insert or UPDATE ON podsumowanie
        FOR EACH ROW
  DECLARE
  z1 varchar2;
  z2 varchar2;
  z3 varchar2;
  BEGIN
  IF :NEW.ognisko=(select o.id 
   from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace!=o.id
   where o.placowka=:NEW.placowka and o.id=:NEW.ognisko)THEN            
    if updating('dzialania_korygujacje_opis') then
      select p.dzialania_korygujacje_opis into z1
      from ognisko o
      join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
      join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
      where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
         IF INSTR(z1,:OLD.dzialania_korygujacje_opis)!=-1 then
           REPLACE(z1,:OLD.dzialania_korygujacje_opis,:NEW.dzialania_korygujacje_opis);
            update podsumowanie pod set pod.dzialania_korygujacje_opis=z1 where
            pod.ID=(
            select p.ID
            from ognisko o
            join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
            join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
            where o.placowka=:NEW.placowka and o.id=:NEW.ognisko);
         END IF;
    end if;
  END IF;
END;

尝试创建它后,我收到错误消息: 错误(8,23):PLS-00103:在期望以下之一时遇到符号 "JOIN":),组具有相交减去开始并集,其中连接

Oracle 版本 11.2.0.1.0 不知道,问题是什么。我一直在寻找很长一段时间!也许您有更好的 google 结果? 数据库:

GRUPY_OGNISK:

ID  NUMBER(38,0)    No      1   
PLACOWKA    NUMBER(38,0)    No      2   
USUNIETE    NUMBER(1,0) No      5   
REF_ID  NUMBER(38,0)    Yes     9   
REF_PLACOWKA    NUMBER(38,0)    Yes     10  
REF_TYP NUMBER(38,0)    No      11  
PROWADZACE  NUMBER(38,0)    Yes     13  
PROWADZACE_PLACOWKA NUMBER(38,0)    Yes     14  
PROWADZACE_IDENTYFIKATOR    VARCHAR2(50 CHAR)   Yes     15  

奥格尼斯科:

ID  NUMBER(38,0)    No      1   
PLACOWKA    NUMBER(38,0)    No      2   
REF_ID  NUMBER(38,0)    Yes     9   
REF_PLACOWKA    NUMBER(38,0)    Yes     10  
REF_TYP NUMBER(38,0)    No      11  
GRUPA   NUMBER(38,0)    Yes     38  

PODSUMOWANIE:

ID  NUMBER(38,0)    No      1   
PLACOWKA    NUMBER(38,0)    No      2   
USUNIETE    NUMBER(1,0) No      5   
REF_ID  NUMBER(38,0)    Yes     9   
REF_PLACOWKA    NUMBER(38,0)    Yes     10  
REF_TYP NUMBER(38,0)    No      11  
DZIALANIA_KORYGUJACJE_OPIS  VARCHAR2(255 CHAR)  Yes     16  
OGNISKO NUMBER(38,0)    No      26  
OGNISKO_PLACOWKA    NUMBER(38,0)    No      27  

只有一些列,因为它们太多了,它们在这里并不重要

错误在这部分:

IF :NEW.ognisko=(select o.id 
   from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace!=o.id
   where o.placowka=:NEW.placowka and o.id=:NEW.ognisko)THEN

您不能在 PL/SQL 条件下使用(子)查询,您需要将值 select 放入局部变量并进行比较。您正在做的事情的简化版本是:

begin
  if 'X' = (select d.dummy from dual d join dual x on x.dummy = d.dummy) then
    null;
  end if;
end;
/

ORA-06550: line 2, column 40:
PLS-00103: Encountered the symbol "JOIN" when expecting one of the following: ...

它抱怨连接,因为这正是解析器首先发现它无法解决的问题的地方;没有加入它仍然会出错,并带有更有意义的消息:

begin
  if 'X' = (select d.dummy from dual d) then
    null;
  end if;
end;
/

ORA-06550: line 2, column 12:
PLS-00405: subquery not allowed in this context

您需要使用局部变量,例如:

declare
  l_dummy dual.dummy%type;
begin
  select dummy into l_dummy from dual;
  if 'X' = l_dummy then
    null;
  end if;
end;
/

或者在您的情况下,定义了合适的变量:

  select o.id into l_id
   from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace!=o.id
   where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
  IF :NEW.ognisko=l_id THEN  

但是由于 select 的 where 条件正在执行 o.id=:NEW.ognisko 那么条件必须为真,除非没有匹配的记录,在这种情况下你会得到未找到数据的错误。如果您要测试是否存在,请改为计数并检查,也许:

  select count(*) into l_count
   from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace!=o.id
   where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
  IF l_count > 0 THEN  

Alex Poole - 谢谢! 如果有人对最终的触发器主体感兴趣,没有错误,我 post 在这里,作为下一代的例子:)

            create or replace trigger trig_ognisko
            before insert or UPDATE ON podsumowanie
            FOR EACH ROW
  DECLARE
  z1 varchar2(1000);
  z2 varchar2(1000);
  z3 varchar2(1000);
  tempID NUMBER;
BEGIN
select o.id into tempID
   from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace!=o.id
   where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
  IF :NEW.ognisko=tempID THEN            
    if updating('dzialania_korygujacje_opis') then
      SELECT p.dzialania_korygujacje_opis INTO z1
      FROM ognisko o1
      JOIN grupy_ognisk g1 ON g1.id=o1.grupa AND g1.placowka=o1.placowka AND g1.prowadzace=o1.id
      JOIN podsumowanie p ON p.ognisko = o1.id AND p.placowka=o1.placowka
      WHERE o1.placowka=:NEW.placowka AND o1.id=:NEW.ognisko;
         IF INSTR(z1,:OLD.dzialania_korygujacje_opis)!=-1 then
           z1:=REPLACE(z1, :OLD.dzialania_korygujacje_opis, :OLD.dzialania_korygujacje_opis);
            update podsumowanie pod set pod.dzialania_korygujacje_opis=z1 where
            pod.ID=(
            select p.ID
            from ognisko o
            join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
            join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
            where o.placowka=:NEW.placowka and o.id=:NEW.ognisko);
         END IF;
    end if;     
   if updating('likwidacja_zrodla_opis') then
      select p.likwidacja_zrodla_opis into z2
      from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
      join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
      where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
        IF INSTR(z2,:OLD.likwidacja_zrodla_opis)!=-1 then
           z2:=REPLACE(z2, :OLD.likwidacja_zrodla_opis, :OLD.likwidacja_zrodla_opis);
            update podsumowanie pod set pod.likwidacja_zrodla_opis=z2 where
            pod.ID=(
            select p.ID
            from ognisko o
            join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
            join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
            where o.placowka=:NEW.placowka and o.id=:NEW.ognisko);
         END IF;
    end if;
     if updating('inne_opis') then
      select p.inne_opis into z3
      from ognisko o join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
      join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
      where o.placowka=:NEW.placowka and o.id=:NEW.ognisko;
        IF INSTR(z2,:OLD.inne_opis)!=-1 then
           z3:=REPLACE(z2, :OLD.inne_opis, :OLD.inne_opis);
            update podsumowanie pod set pod.inne_opis=z3 where
            pod.ID=(
            select p.ID
            from ognisko o
            join grupy_ognisk g on g.id=o.grupa and g.placowka=o.placowka and g.prowadzace=o.id
            join podsumowanie p on p.ognisko = o.id and p.placowka=o.placowka
            where o.placowka=:NEW.placowka and o.id=:NEW.ognisko);
         END IF;
    end if;
  END IF;
END;

  drop trigger trig_ognisko;
  select* from V$VERSION;