Oracle SQL,避免错误“表正在变异”(触发器)

时间:2014-06-07 14:34:54

标签: sql oracle plsql

我需要触发器,它会检查更新的工作人员是否可以移动到其他团队

CREATE TABLE WORKERS 
(   
    ID_WORKER NUMBER(4,0), --FK
    ID_TEAM NUMBER(2,0) --FK
);

我的触发器如下:

CREATE OR REPLACE TRIGGER TEAM_LIMIT
BEFORE INSERT OR UPDATE OF ID_TEAM ON WORKERS
FOR EACH ROW
DECLARE
  V_num NUMBER;
BEGIN
  SELECT Count(*) INTO V_num FROM Worker WHERE ID_TEAM=:new.ID_TEAM;
  IF V_num >= 5 THEN
    RAISE_APPLICATION_ERROR(-20025,' Error nr ... bleble');
  END IF;
END; 

这会产生错误:"表%s。%s正在变异,触发/功能可能看不到它"当行更新时。如何正确编写此语句以避免产生此类错误?

2 个答案:

答案 0 :(得分:0)

您可以使用复合触发器,它看起来像这样(未经测试):

CREATE OR REPLACE TRIGGER TEAM_LIMIT
FOR INSERT OR UPDATE OF ID_TEAM ON WORKERS 
COMPOUND TRIGGER

V_num NUMBER;

TYPE Row_TableType IS TABLE OF WORKERS.ID_TEAM%TYPE;
AffectedTeams Row_TableType;    

BEFORE STATEMENT IS
BEGIN
    AffectedTeams := Row_TableType(); -- init the table variable   
END BEFORE STATEMENT;
-------------------
BEFORE EACH ROW IS
BEGIN
    AffectedTeams.EXTEND;
    AffectedTeams(AffectedTeams.LAST) := :NEW.ID_TEAM;
END BEFORE EACH ROW;
--------------------
AFTER STATEMENT IS
BEGIN
    FOR i IN AffectedTeams.FIRST..AffectedTeams.LAST LOOP
       SELECT Count(*) INTO V_num FROM Worker WHERE ID_TEAM=AffectedTeams(i);
       IF V_num >= 5 THEN
          RAISE_APPLICATION_ERROR(-20025,' Error nr ... bleble');
       END IF;        
    END LOOP;
END AFTER STATEMENT;

END TEAM_LIMIT;
/

答案 1 :(得分:0)

您可以使用语句触发器。语句触发器仅对每个执行的语句触发一次,而不是对每个受影响的行触发一次。语句触发器非常有用,因为它们没有限制,无法查询声明触发器的表。他们无法访问:OLD和:NEW行值,但稍微想一想,您仍然可以完成您尝试做的事情:

CREATE OR REPLACE TRIGGER TEAM_LIMIT
  BEFORE INSERT OR UPDATE OF ID_TEAM ON WORKERS
  -- Note: no FOR EACH ROW - therefore, this is a statement trigger
DECLARE
  nMax_team_count  NUMBER;
BEGIN
  SELECT MAX(TEAM_COUNT)
    INTO nMax_team_count
    FROM (SELECT ID_TEAM, COUNT(*) AS TEAM_COUNT
            FROM WORKERS
            GROUP BY ID_TEAM));

  IF nMax_team_count >= 5 THEN
    RAISE_APPLICATION_ERROR(-20025,' Error nr ... bleble');
  END IF;
END TEAM_LIMIT;

不是查看已更新的特定工作的团队,而是查找每个团队的工人数量,然后提取最大数量,如果超过四个,我们会提出相应的例外情况。< / p>

分享并享受。