【问题标题】:Oracle 11g Trigger Error - ORA-00923: FROM keyword not found where expectedOracle 11g 触发错误 - ORA-00923: FROM 关键字未在预期位置找到
【发布时间】:2020-11-08 09:18:17
【问题描述】:

我对 Oracle SQL(特别是 Oracle 11g SQL)还是很陌生。我正在尝试编写触发器,但似乎无法解决所有错误。目前,当我尝试执行下面列出的 SQL 时,出现此错误:

Error at line 12: PL/SQL: ORA-00923: FROM keyword not found where expected

1. CREATE OR REPLACE TRIGGER course_assignment_trigger
2. AFTER INSERT ON Assign FOR EACH ROW
3. DECLARE

这是我的 SQL:

CREATE OR REPLACE TRIGGER course_assignment_trigger
AFTER INSERT ON Assign FOR EACH ROW
DECLARE
   tooManyCourses EXCEPTION;
   notQualified EXCEPTION;
   assignedBeforeQualified EXCEPTION;
   assignedCourseCount int;
   qualifiedRowCount int;
   PRAGMA EXCEPTION_INIT( tooManyCourses, -20001 );
   PRAGMA EXCEPTION_INIT( notQualified, -20001 );
   PRAGMA EXCEPTION_INIT( assignedBeforeQualified, -20001 );


BEGIN
   SELECT assignedCourseCount = COUNT(*) FROM Assign where Fid = :new.Fid;
   IF assignedCourseCount  >= 3
   THEN
       RAISE tooManyCourses;
   END IF;

   SELECT qualifiedRowCount = COUNT(*) FROM Qualify where Fid = :new.Fid and Cid = :new.Cid;
   IF qualifiedRowCount = 0
   THEN
       RAISE notQualified;
   END IF;

   IF(:new.assignDate < (select qualifyDate from Qualify where Fid = :new.Fid and Cid = :new.Cid))
   THEN
       RAISE unacceptedDateOfQualification;
   END IF;

EXCEPTION
   WHEN tooManyCourses THEN
       DBMS_OUTPUT.PUT_LINE('Cannot assign faculty to more than 3 courses.');

   WHEN notQualified THEN
       DBMS_OUTPUT.PUT_LINE('Faculty is not qualified to teach the course.');

   WHEN assignedBeforeQualified THEN
       DBMS_OUTPUT.PUT_LINE('Date of qualification must be before date of assignment.');

END;

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    你快到了。

    语法是:

    SELECT column_identifier
    INTO   plsql_variable
    FROM   table
    -- ...
    

    当您将异常声明为assignedBeforeQualified 时,您RAISE unacceptedDateOfQualification 需要给每个异常一个不同的错误号。但是,您几乎肯定不想引发自定义异常并在同一个触发器中捕获它们并输出到控制台,因为它不会阻止 INSERT 的发生;您想 RAISE_APPLICATION_ERROR 使用您的自定义错误消息并想要这样做 BEFORE INSERT

    像这样:

    CREATE OR REPLACE TRIGGER course_assignment_trigger
    BEFORE INSERT ON Assign FOR EACH ROW
    DECLARE
       assignedCourseCount int;
       qualifiedRowCount int;
       qualifyDt DATE;
    BEGIN
       SELECT COUNT(*)
       INTO   assignedCourseCount
       FROM   Assign
       where Fid = :new.Fid;
       
       IF assignedCourseCount  >= 3
       THEN
           RAISE_APPLICATION_ERROR( -20001, 'Cannot assign faculty to more than 3 courses.');
       END IF;
    
       SELECT COUNT(*)
       INTO   qualifiedRowCount
       FROM   Qualify
       where  Fid = :new.Fid
       and    Cid = :new.Cid;
    
       IF qualifiedRowCount = 0
       THEN
           RAISE_APPLICATION_ERROR( -20002, 'Faculty is not qualified to teach the course.');
       END IF;
    
       select MIN(qualifyDate)
       INTO   qualifyDt
       from   Qualify
       where  Fid = :new.Fid
       and    Cid = :new.Cid;
       
       IF :new.assignDate < qualifyDt
       THEN
           RAISE_APPLICATION_ERROR( -20003, 'Date of qualification must be before date of assignment.' );
       END IF;
    END;
    /
    

    如果你有桌子:

    CREATE TABLE assign (
      FID number,
      CID number,
      assignDate DATE
    );
    
    CREATE TABLE qualify (
      FID number,
      CID number,
      qualifyDate DATE
    );
    

    然后:

    INSERT INTO assign VALUES ( 1, 1, DATE '2020-01-01' );
    

    引发异常:

    ORA-20002: Faculty is not qualified to teach the course.
    ORA-06512: at "FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER", line 24
    ORA-04088: error during execution of trigger 'FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER'
    

    然后:

    INSERT INTO qualify VALUES ( 1, 1, DATE '2020-01-01' );
    INSERT INTO assign VALUES ( 1, 1, DATE '2020-01-01' );
    

    有效但:

    INSERT INTO assign VALUES ( 1, 1, DATE '2019-01-01' );
    

    引发异常:

    ORA-20003: Date of qualification must be before date of assignment.
    ORA-06512: at "FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER", line 35
    ORA-04088: error during execution of trigger 'FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER'
    

    和:

    INSERT INTO assign VALUES ( 1, 1, DATE '2020-01-01' );
    INSERT INTO assign VALUES ( 1, 1, DATE '2020-01-01' );
    INSERT INTO assign VALUES ( 1, 1, DATE '2020-01-01' );
    

    插入行的第 2 和第 3 个副本,但第 4 个副本引发异常:

    
    ORA-20001: Cannot assign faculty to more than 3 courses.
    ORA-06512: at "FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER", line 13
    ORA-04088: error during execution of trigger 'FIDDLE_BLJCMOGDEOXTZOEWHDDA.COURSE_ASSIGNMENT_TRIGGER'
    

    db小提琴here

    【讨论】:

    • 这正是我需要的!太感谢了!我当然不知道引发自定义异常不会阻止插入(在您的答案中包含的其他语法更正中)。再次感谢!
    • @ChapterSevenSeeds 如果引发BEFORE INSERT(而不是AFTER INSERT),引发任何异常都会阻止插入,但您的问题是您正在捕获异常并尝试输出到控制台。用户不会看到控制台的输出,也不会传播异常(因为您已经捕获并处理了它),因此不会停止任何事情。您需要引发异常而不是捕获它。
    • 是的,我也注意到了。我将其更改为“插入后”,因为这是预期的功能。另外,感谢您对异常的进一步解释。我很惊讶我没有意识到它就像任何其他具有异常处理的语言一样(抛出它并且不要捕获它以显示系统生成的错误消息)。哦,在一个下午从互联网上学习大学作业材料的麻烦。
    • @ChapterSevenSeeds 你用AFTER INSERT 测试过吗?它会在每次插入 db<>fiddle 时引发 ORA-04091: table FIDDLE_XHTVJTOGXWAVJLHUHUDM.ASSIGN is mutating, trigger/function may not see it
    • 是的,这就是我改变它的原因。没有插入行(这是我最初想要的),但该错误消息似乎不合时宜。再一次,基本上所有触发器的声明都是直接来自互联网,没有太多上下文。我对修复身体非常执着,以至于我没有看到那里明显的“插入后”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 2019-08-22
    • 2020-08-03
    • 2017-08-08
    相关资源
    最近更新 更多