PL/SQL触发器未检测到

PL/SQL触发器未检测到,sql,oracle,plsql,database-trigger,Sql,Oracle,Plsql,Database Trigger,嗨,我在大学学习触发器,我正在尝试实现一个简单的函数来理解逻辑。我试图创建一个触发器,禁止员工同时拥有超过4个项目。 所有编译都正确,但是当我通过向员工添加第5个项目来测试触发器时,触发器不会检测到它。有人能用我的逻辑解释我做错了什么吗 CREATE OR REPLACE TRIGGER MAXPROJECTS BEFORE INSERT OR UPDATE ON WorksOn FOR EACH ROW DECLARE PRAGMA AUTONOMOUS_TRANSACTION; pro

嗨,我在大学学习触发器,我正在尝试实现一个简单的函数来理解逻辑。我试图创建一个触发器,禁止员工同时拥有超过4个项目。 所有编译都正确,但是当我通过向员工添加第5个项目来测试触发器时,触发器不会检测到它。有人能用我的逻辑解释我做错了什么吗

CREATE OR REPLACE TRIGGER MAXPROJECTS 
BEFORE INSERT OR UPDATE
ON WorksOn FOR EACH ROW

DECLARE 
PRAGMA AUTONOMOUS_TRANSACTION;
project_count INT(10);

BEGIN

SELECT COUNT(p#) INTO project_count
FROM WorksOn WHERE e# =:NEW.e#;

IF (project_count > 4) 
THEN RAISE_APPLICATION_ERROR(-20010, 
'employee is already working on 4 
projects.');
END IF;
END;
/

PRAGMA autonomy_事务
意味着您的触发器将在其自己的事务中运行。由于它是一个单独的事务,因此它无法查看您刚才插入的未提交的数据,因此insert语句不会失败


此杂注主要用于“副作用”触发器(例如,记录到另一个表),您不希望“副作用”中的失败导致整个操作失败。在这个用例中,您期望的正好相反,因此不应该使用这个pragma。

这里有几个问题

首先,我猜您试图在没有PRAGMA自治事务的情况下使其成为行触发器,但它在您身上爆炸了,因此您搜索了StackOverflow,发现了使用此PRAGMA绕过“mutating table”异常的方法,但这仍然不适用于您

就能够计算分配给员工的项目数量而言,有两种不同的方法可以实现您的目标,但最简单的方法是将其作为语句触发器,而不是行触发器,这是通过在触发器定义中省略每行的
子句来完成的。语句触发器只对每个语句触发一次,而不是对受语句影响的每一行触发一次,并且您没有访问:NEW或:OLD值的权限-但是如果您想对了,您就会意识到您实际上并不需要这些值

其次,您已经将此设置为在语句执行之前触发的BEFORE触发器,因此该语句将要进行的更改在触发器中不可见。所以这需要是一个后触发器

以下内容应满足您的要求

CREATE OR REPLACE TRIGGER WORKSON_BIU_STMT
  AFTER INSERT OR UPDATE
  ON WorksOn
BEGIN
  FOR aRow IN (SELECT e#, COUNT(DISTINCT p#) AS PROJECT_COUNT
                 FROM WorksOn
                 GROUP BY e#)
  LOOP
    DBMS_OUTPUT.PUT_LINE('E#=' || aRow.E# || '  PROJECT_COUNT=' || aRow.PROJECT_COUNT);

    IF aRow.PROJECT_COUNT > 4 THEN
      RAISE_APPLICATION_ERROR(-20010, 'Employee ' || aRow.e# || ' cannot be assigned to ' || aRow.PROJECT_COUNT || ' projects.');
    END IF;
  END LOOP;
END WORKON_BIU_STMT;

因为
自主交易
pragma。触发器(select语句)只看到提交的数据。如果每个
INSERT
UPDATE
语句都是一个单独的事务(您需要在每个
INSERT
UPDATE
语句之后提交),并且如果条件从
project\u count>N
更改为
project\u count>N-1,则可以使其以您期望的方式工作。但我建议不要在触发器中实现这种逻辑。在存储过程(API)中实现它,而不是在这里使用Pragma autonomy_TRANSACTION=Start Bug。顺便说一句,这种业务规则很难实现,触发器可能不是正确的方法。首先,如果同一名员工同时被分配到五个单独的会议中的五个项目,该怎么办?触发器只能看到其他会话提交的数据。鲍勃·贾维斯,我太爱你了。