【问题标题】:Oracle SQL Trigger SyntaxOracle SQL 触发器语法
【发布时间】:2020-07-21 16:44:12
【问题描述】:

我正在尝试创建一个触发器来检查要添加到分配表的教员是否已经在指定班级的合格表上。也许这是一种乏味的方法。尽管如此,我仍然想知道我做错了什么。以下是我的代码,其中创建了创建的表,触发器是代码的最后一部分:

代码:

CREATE TABLE Faculty (
  FId varchar(10),
  FName varchar(20),
  CONSTRAINT Faculty_ID_pk PRIMARY KEY(FId)
);

CREATE TABLE Course (
  CId varchar(10),
  CName varchar(20),
  CONSTRAINT Course_ID_pk PRIMARY KEY(CId)
);

CREATE TABLE Qualify (
  QDate DATE,
  FId varchar(10),
  CId varchar(10),
  CONSTRAINT Qualifying_date CHECK(QDate >= TO_DATE('2020-08-24', 'YYYY-MM-DD')),
  CONSTRAINT Qualify_FID_fk FOREIGN KEY(FId) REFERENCES Faculty(FId),
  CONSTRAINT Qualify_CID_fk FOREIGN KEY(CId) REFERENCES Course(CId)
);

CREATE TABLE Assign (
  ADate DATE,
  FId varchar(10),
  CId varchar(10),
  CONSTRAINT Qualifying_check CHECK(ADate > TO_DATE('2020-08-24', 'YYYY-MM-DD')),
  CONSTRAINT Assign_FID_fk FOREIGN KEY(FId) REFERENCES Faculty(FId),
  CONSTRAINT Assign_CID_fk FOREIGN KEY(CId) REFERENCES Course(CId)
);



CREATE OR REPLACE TRIGGER Check_If_Qualified
   BEFORE INSERT ON Assign
   FOR EACH ROW
DECLARE
   v_facNum number;
BEGIN
   SELECT f.FId
      into v_facNum
      from Faculty f
      where f.facnum = :new.fid;
END;

但是,我一直收到一条错误消息:

第 7 行错误:PLS-00225:子程序或游标“F”引用超出范围

  1. v_facNum 号码;
  2. 开始
  3. 选择 f.FId
  4. 进入 v_facNum
  5. 来自学院 f

有谁知道哪里出了问题?

【问题讨论】:

    标签: sql oracle triggers


    【解决方案1】:

    应该是这样的(示例表实际上只是一个示例;它们在这里是为了使触发器编译):

    SQL> create table assign (fid number);
    
    Table created.
    
    SQL> create table faculty (facnum number, fid number);
    
    Table created.
    
    SQL> CREATE OR REPLACE TRIGGER Check_If_Qualified
      2    BEFORE INSERT ON Assign
      3    FOR EACH ROW
      4  DECLARE
      5    v_facNum number;
      6  BEGIN
      7     SELECT f.FId
      8       into v_facNum
      9       from Faculty f
     10       where f.facnum = :new.fid;
     11
     12    -- now do something with v_facNum
     13  END;
     14  /
    
    Trigger created.
    
    SQL>
    

    【讨论】:

    • 好的,我现在得到的错误是:“子程序或游标 'F' 引用超出范围” 也许我应该提到我对 SQL 很陌生。这个错误是什么意思?是因为“F”未定义吗?
    • 你做错了;我通过创建这些表编辑了我之前发布的代码 - 触发器编译成功。如果您的代码不起作用,请编辑您的原始消息并发布复制/粘贴您的 SQL*Plus 会话(就像我所做的那样),以便我们可以看到您到底做了什么以及 Oracle 是如何响应的。
    • 好的,我已经用我创建表格的方式更新了代码。也许我应该提到这些表在创建时包含约束。这可能是问题吗?我是否需要从表中删除所有预定义的约束才能为它们创建触发器?
    • 好吧,我想通了!当我用表名“Faculty”替换“f”并将 f.facnum 更改为 Faculty.FId 时,它起作用了。不过,非常感谢您的帮助!现在,我可以在插入之前检查合格表中是否存在教员编号。如果没有,我可以停止插入,因为如果教员没有资格教授课程,触发器需要确保他们没有被分配教授课程。
    • 很高兴你成功了;感谢您让我们知道!
    【解决方案2】:

    您的代码中有很多问题。您可以将记录数检查到FACULTY 表中,并将该计数用于您想要的任何逻辑。

    CREATE OR REPLACE TRIGGER CHECK_IF_QUALIFIED 
        BEFORE INSERT ON ASSIGN
        FOR EACH ROW
    DECLARE
        CNT   NUMBER;
    BEGIN
        SELECT COUNT(1)
          INTO CNT
          FROM FACULTY
         WHERE FACNUM = :NEW.FID;
    END;
    /
    

    【讨论】:

    • 我不确定这是否有效,因为现在它说:“SQL 语句被忽略” 计数是否返回 FACULTY 表中的第一条记录?
    猜你喜欢
    • 2016-05-20
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    • 2018-04-04
    • 1970-01-01
    相关资源
    最近更新 更多