我有一个功能:
CREATE OR REPLACE FUNCTION delete_student()
RETURNS TRIGGER AS
$BODY$
BEGIN
IF (TG_OP = 'DELETE')
THEN
INSERT INTO cancel(eno, excode,sno,cdate,cuser)
VALUES ((SELECT entry.eno FROM entry
JOIN student ON (entry.sno = student.sno)
WHERE entry.sno = OLD.sno),(SELECT entry.excode FROM entry
JOIN student ON (entry.sno = student.sno)
WHERE entry.sno = OLD.sno),
OLD.sno,current_timestamp,current_user);
END IF;
RETURN OLD;
END; $BODY$ LANGUAGE plpgsql;
我也有触发器:
CREATE TRIGGER delete_student
BEFORE DELETE
on student
FOR EACH ROW
EXECUTE PROCEDURE delete_student();
这个想法是当我从学生关系中删除学生时,条目关系中的条目也会删除,我的取消关系会更新。
这就是我对学生的关系:
INSERT INTO
student(sno, sname, semail) VALUES (1, 'a. adedeji', 'ayooladedeji@live.com');
这就是我加入我的入门关系:
INSERT INTO
entry(excode, sno, egrade) VALUES (1, 1, 98.56);
当我执行命令
时DELETE FROM student WHERE sno = 1;
它会删除学生以及相应的条目并且查询返回时没有错误但是当我在取消表上运行select时,表显示为空?
答案 0 :(得分:0)
您没有显示如何删除相应的entry
。如果在student
记录之前删除该条目,则会导致该问题,因为触发器中的INSERT
将失败,因为SELECT
语句将不提供要插入的任何值。是否通过entry
上的CASCADING删除删除了相应的student
?
此外,您的触发器可以更简单:
CREATE OR REPLACE FUNCTION delete_student() RETURNS trigger AS $BODY$
BEGIN
INSERT INTO cancel(eno, excode, sno, cdate, cuser)
VALUES (SELECT eno, excode, sno, current_timestamp, current_user
FROM entry
WHERE sno = OLD.sno);
RETURN OLD;
END; $BODY$ LANGUAGE plpgsql;
首先,该功能仅在DELETE
触发器上触发,因此您无需测试TG_OP
。其次,在INSERT
语句中,您永远不会访问student
关系中的任何数据,因此不需要JOIN
该关系; sno
确实来自学生关系,但是来自OLD
隐式参数。
答案 1 :(得分:0)
您没有发布您的数据库架构,并且您的问题不是很清楚,但看起来级联删除正在干扰某处。具体做法是:
student
之前,您需要在引用它的cancel
中插入内容。student
中的行。entry
和... cancel
中的行(包括您刚刚插入的行)。一些评论:
首先,作为经验法则,before
触发器除了行本身之外不应该对任何东西产生副作用。在before delete
触发器中插入行是一个很大的问题:除了引入相关的潜在问题,例如Postgres在完成查询时报告错误的FOUND值或不正确的行数,请考虑单独的before
触发器的情况通过返回NULL
完全取消删除。因此,您的触发器函数应该在after
触发器上运行 - 只有在那时您才能确定该行确实已被删除。
其次,你不需要这些低效,冗余和丑陋的子选择语句。请改用insert ... select ...
种插页:
INSERT INTO cancel(eno, excode,sno,cdate,cuser)
SELECT entry.eno entry.excode, OLD.sno, current_timestamp, current_user
FROM entry
WHERE entry.sno = OLD.sno;
第三,你的触发器可能应该在条目表上运行,如下所示:
INSERT INTO cancel(eno, excode,sno,cdate,cuser)
SELECT OLD.eno OLD.excode, OLD.sno, current_timestamp, current_user;
最后,您的架构中可能存在一些问题。如果entry
中的每一行student
都有一个唯一的行,并且您需要entry
中的信息才能使您的触发器工作以填充cancel
,表示应该合并两个表(student
和entry
)。无论是否合并它们,您可能还需要删除(或手动管理)适用的某些级联删除,以便按照运行所需的顺序强制执行业务逻辑。