【问题标题】:PL/SQL Comparison error in trigger (PLS-00405)触发器中的 PL/SQL 比较错误 (PLS-00405)
【发布时间】:2015-03-18 21:33:57
【问题描述】:

我正在尝试制作一个简单的触发器,它必须在插入和更新时检查给定的值。我必须检查 ID 是否与 NAVAZUJE_NA(外键引用 ID)不同。代码如下:

CREATE OR REPLACE TRIGGER PREDMETY_INSERT_TRIGGER 
BEFORE INSERT OR UPDATE ON PREDMETY 
FOR EACH ROW
BEGIN
  IF :NEW.ID = :NEW.NAVAZUJE_NA THEN --There is an error (PLS-00405) 
    RAISE_APPLICATION_ERROR(-20000, 'Predmet nemuze navazovat sam na sebe.', FALSE);
  ELSIF :NEW.NAVAZUJE_NA > (SELECT MAX(ID) FROM PREDMETY) THEN
    RAISE_APPLICATION_ERROR(-20001, 'Predmet nemuze navazovat na neexistujici predmet.', FALSE);
  ELSIF :NEW.ID < 0 OR :NEW.NAVAZUJE_NA < 0 THEN
    RAISE_APPLICATION_ERROR(-20002, 'Neplatny index predmetu nebo predmetu, na ktery ma dany predmet navazovat.', FALSE);
  END IF;
    EXCEPTION
        WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('[ERROR] '||sqlerrm);
END;

感谢您的任何解决方案。

【问题讨论】:

  • 我不明白你的要求。通常,表上的行级触发器无法查询该表。所以你不能在predmety 的行级触发器中运行select max(id) from predmety。您也不能以这种方式将查询放在IF 子句中——您需要在IF 语句之前填充一个单独的变量。并且抛出异常只是为了捕获它们并尝试将它们打印到dbms_output 非常非常不可能是合理的。
  • 谢谢,已解决。将错误打印到dbms_output 仅用于学术目的。
  • @Justin Cave 实际上,您可以在行级触发器中从表中运行 select max(id) 到变量中,这是可行的。它不适用于返回更多行的查询
  • @Mina - 问题不在于查询将返回的行数。问题是您通常无法在表A 的行级触发器中查询表A。是的,如果您只允许 INSERT 操作并且如果每个 INSERT 都是单行 INSERT ... VALUES,那么它将起作用。但这是一个相当严格的限制。

标签: oracle plsql triggers


【解决方案1】:

如果您有 11g 或 12c,则可以编写复合触发器。它有一个在实际触发活动开始之前执行的部分。也就是说,您可以从该部分的表中读取,因为这是在表进入变异状态之前:

create or replace trigger Predmety_Ciu
For Insert Or Update On Predmety
Compound Trigger
    MaxID   int;

    Before Statement Is Begin
        -- Be prepared this might be the first record written to the table
        select nvl( max( ID ), 0 ) into MaxID from Predmety;
    End Before Statement;

    Before Each Row Is Begin
      IF :NEW.ID = :NEW.NAVAZUJE_NA THEN --There is an error (PLS-00405) 
        Raise_Application_Error(-20000, 'Predmet nemuze navazovat sam na sebe.', False);
      Elsif :New.Navazuje_Na > Maxid Then
        Raise_Application_Error(-20001, 'Predmet nemuze navazovat na neexistujici predmet. Další objekt ID: ' || to_char( Maxid ), False);
      Elsif :New.Id < 0 Or :New.Navazuje_Na < 0 Then
        Raise_Application_Error(-20002, 'Neplatny index predmetu nebo predmetu, na ktery ma dany predmet navazovat.', False);
      End If;
    End Before Each Row;

    After Each Row Is Begin
        -- Vložte nějaký kód, který chcete spustit po vložení řádku
        If Inserting Then
            Maxid := Maxid + 1;
        end if;
    End After Each Row;

    After Statement Is Begin
        Null; -- Vložte nejaký kód, který chcete spustit po zadání všech rádek.
    End After Statement;
End Predmety_Ciu;

我删除了异常处理程序,因为我想要异常。

【讨论】:

    【解决方案2】:

    当您将最大 id 提取到变量中并在 if 语句中使用变量时,它会起作用。

    CREATE OR REPLACE TRIGGER PREDMETY_INSERT_TRIGGER 
    BEFORE INSERT OR UPDATE ON PREDMETY 
    FOR EACH ROW
    declare 
    c number;
    BEGIN
      SELECT MAX(ID) into c FROM PREDMETY;
      IF :NEW.ID = :NEW.NAVAZUJE_NA THEN --There is an error (PLS-00405) 
        RAISE_APPLICATION_ERROR(-20000, 'Predmet nemuze navazovat sam na sebe.', FALSE);
      ELSIF :NEW.NAVAZUJE_NA > c THEN
        RAISE_APPLICATION_ERROR(-20001, 'Predmet nemuze navazovat na neexistujici predmet.', FALSE);
      ELSIF :NEW.ID < 0 OR :NEW.NAVAZUJE_NA < 0 THEN
        RAISE_APPLICATION_ERROR(-20002, 'Neplatny index predmetu nebo predmetu, na ktery ma dany predmet navazovat.', FALSE);
      END IF;
        EXCEPTION
            WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('[ERROR] '||sqlerrm);
    END;
    

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2014-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多