0

我在 Oracle SQL 上做一个大学项目,当我尝试更新表时,我不断收到错误“表 (...) 正在变异,触发器/函数可能看不到它”。我的partiteTeams表有 3 列(eventName varchar(), teamId number, teamPlace number)

这里的目标是,当我在活动中更新给定团队的 teamPlace 时,该位置必须小于或等于同一活动中参与团队的数量。

我的触发器如下:

Before update on participateTeams
for each row
Declare participants number;
Begin
     select count(*) into participants from participateteams where :New.eventName = participateteams.eventName;

        if(:NEW.teamplace>participants) then
            RAISE_APPLICATION_ERROR(-20250,'O lugar da equipa é inválido');
        end if;
End;
/

根据我的研究,这是因为我正在尝试读取调用触发器的同一张表。我也尝试将代码的选择部分导出到函数中,但问题仍然存在。

活动的参与者是团队本身,而不是组成这些团队的个人。示例:如果 A 队、B 队和 C 队参加了一项赛事 E,则同一赛事 E 的计数应为 3。

有小费吗?谢谢你。

4

2 回答 2

0

变异表错误只是一种痛苦。而你正在尝试做的是相当棘手的。这是一种方法:

  1. 添加一个teams包含参与者数量的列。
  2. insert使用/维护此列update,并delete在 上触发participateteams
  3. 编写一个用户定义的函数来获取给定团队的计数。
  4. 在使用用户定义的函数时添加一个check约束。participateteams
于 2020-05-23T16:06:58.227 回答
0

您想要实现的逻辑上正确的触发器是:-

CREATE OR REPLACE TRIGGER TRIG_CHK
AFTER INSERT OR UPDATE OF teamPlace ON participateteams
FOR EACH ROW
DECLARE
participants NUMBER;
BEGIN
 select count(*) into participants from participateteams where :New.eventName = 
 participateteams.eventName;
    if(:NEW.teamplace>participants) then
        RAISE_APPLICATION_ERROR(-20250,'O lugar da equipa é inválido');
    end if;
End;    
update participateteams set teamPlace = 2 where eventName = 'B';

但是当它在尝试更新表参与团队时出现变异表错误时,为了解决这个棘手的情况,我所做的是:-

step1 : 在包头中声明需要的表列

CREATE OR REPLACE PACKAGE PKG_TEAMS AS
v_eventName participateteams.eventName%type;
v_teamPlace participateteams.teamPlace%type;
end;

step2:初始化行级触发器中的变量

CREATE OR REPLACE TRIGGER TRG_row
AFTER INSERT OR UPDATE OF teamPlace
ON participateteams
FOR EACH ROW
BEGIN
PKG_TEAMS.v_eventName := :NEW.eventName;
PKG_TEAMS.v_teamPlace := :NEW.teamPlace;
END;

step3:现在,而不是使用 :NEW 伪列,使用全局初始化变量

  CREATE OR REPLACE TRIGGER TRG_stmt
AFTER INSERT OR UPDATE OF teamPlace ON participateteams
DECLARE 
v_participants NUMBER;
BEGIN
SELECT COUNT(*) INTO v_participants FROM participateteams
WHERE eventName = PKG_TEAMS.v_eventName;
 if(PKG_TEAMS.v_teamPlace>v_participants) then
            RAISE_APPLICATION_ERROR(-20250,'CANNOT UPDATE,AGAINST RULES');
        end if;
End; 
于 2020-05-24T02:25:47.847 回答