PLSQL 中的触发器问题
Posted
技术标签:
【中文标题】PLSQL 中的触发器问题【英文标题】:Trigger problems in PLSQL 【发布时间】:2014-03-08 20:56:13 【问题描述】:我一直在尝试获得一个基本上会运行这样的约束的触发器; 约束(日期
它将一个表格(比赛)中的日期与另一表格(会议)中的日期进行比较。我知道我可以使用外键来实现这一点,但我很确定会获得更多我需要使用触发器的标记。
到目前为止,我得到了这个:
CREATE OR REPLACE TRIGGER race_date_trg
AFTER INSERT OR UPDATE
ON RACE
FOR EACH ROW
DECLARE
MEETING_ENDDATE DATE;
STARTDATE race.racedate%TYPE;
BEGIN
SELECT ENDDATE INTO MEETING_ENDDATE FROM meeting;
IF STARTDATE > MEETING_ENDDATE THEN
RAISE_APPLICATION_ERROR(-20000, 'Wrong start date!');
END IF;
end race_date_trg;
它编译得很好,但是当我尝试用会引发错误的东西填充我的表时,我得到了这个:
Error report:
SQL Error: ORA-04091: table SE488.MEETING is mutating, trigger/function may not see it
ORA-06512: at "SE488.RACE_DATE_TRG", line 5
ORA-04088: error during execution of trigger 'SE488.RACE_DATE_TRG'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
感谢您的帮助。
创建表格:
CREATE TABLE Meeting
(
MeetLocation varchar2(60),
StartDate date,
EndDate date,
MeetName varchar2(60)
);
CREATE TABLE Race
(
RaceID NUMBER,
RaceLocation varchar2(60),
MeetingStart date,
RaceDate date,
RaceTime timestamp(0),
RaceName varchar2(60),
RaceType varchar2(8),
MinAge numeric(2),
MaxAge numeric(2),
Sex varchar2(2) NULL
);
填充它们:
INTO Meeting (MeetLocation,StartDate,EndDate,MeetName)
values('Talbot','30-Jul-05','07-Aug-05','Midlands Derby')
INTO Meeting (MeetLocation,StartDate,EndDate,MeetName)
values('Ascot','04-Jul-10','07-Aug-10','National Derby')
INTO Race (RaceID,RaceLocation,MeetingStart,RaceDate,RaceTime,RaceName,RaceType,MinAge,MaxAge,Sex)
values('1','Talbot','20-Jul-05','31-Jul-05',to_date('2005/07/31:12:00:00PM', 'yyyy/mm/dd:hh:mi:sspm'),'600m Dash','Flat','2','10','M')
INTO Race (RaceID,RaceLocation,MeetingStart,RaceDate,RaceTime,RaceName,RaceType,MinAge,MaxAge,Sex)
values('2','Talbot','30-Jul-05','01-Aug-05',to_date('2005/08/01:01:10:00PM', 'yyyy/mm/dd:hh:mi:sspm'),'1km Hurdles','Flat','6','12','F')
【问题讨论】:
race
上的INSERT
或UPDATE
是否来自MEETING
表上定义的另一个触发器?
Mihai,我在使用 BEFORE 时也遇到了同样的错误。 @JustinCave,我不这么认为 - 这是我唯一的触发器。
发布一个可重现的测试用例。发布 DDL 以创建两个表。如果需要该数据来重现问题,请发布 DML 以填充表。发布您正在使用的导致触发器触发的语句。
@Naffel - 缺少一些东西,您提供的代码不会给出该错误。查询user_triggers
和/或user_objects
,看看是否有你忘记的东西。也许是您为之前的尝试创建的触发器?
“我很肯定会得到更多我需要使用触发器的分数” 做出糟糕的设计决定的可怕原因。触发器很少是正确的实现。
【参考方案1】:
CREATE OR REPLACE TRIGGER race_date_trg
BEFORE INSERT OR UPDATE ON RACE
FOR EACH ROW
DECLARE
meet_date date;
start_date date := :new.RaceDate;
BEGIN
SELECT StartDate INTO meet_date FROM meeting WHERE MeetLocation = :new.RaceLocation;
IF start_date > meet_date THEN
RAISE_APPLICATION_ERROR(-20000, 'Wrong start date!');
END IF;
END race_date_trg;
/
我认为您想要引发错误或异常。当有人插入或更新餐桌比赛时,如果开始日期(来自餐桌比赛)低于开会日期(来自餐桌会议)。 :D
【讨论】:
我仍然遇到同样的错误,即使数据不应该出现错误。 :// 您是否删除了旧触发器?您必须先删除旧触发器。 :D以上是关于PLSQL 中的触发器问题的主要内容,如果未能解决你的问题,请参考以下文章
每行设置 new.column 的 PLSQL 触发器不起作用