触发器从另一个表中删除行

Posted

技术标签:

【中文标题】触发器从另一个表中删除行【英文标题】:Trigger to delete row from another table 【发布时间】:2019-12-30 15:04:17 【问题描述】:

我有两张表,分别是 FORUM 和 COMMENTS

论坛主键:论坛ID

评论外键:FORUMID

当用户想要删除论坛中的任何一行时,必须先执行触发器并删除该论坛中的 cmets

CREATE OR REPLACE trigger trg_delete_comments
BEFORE DELETE ON forum
FOR EACH ROW
DECLARE 
   v_forumID varchar(14);
   v_user    varchar(20);
BEGIN
   select forumID into v_forumID
   from forum
   where forumID =:OLD.forumID;

   DELETE COMMENTS
   WHERE FORUMID = v_forumID;
END;
/

当我尝试执行此触发器时,我收到“ORA-04091:表 FORUM 正在变异,触发器/函数可能看不到它”的错误。有什么办法可以解决吗?谢谢

【问题讨论】:

【参考方案1】:

您所描述的是可以通过外键约束轻松提供的功能。您可以使用on delete cascade 子句配置约束,以便在删除父记录时也删除子记录。

考虑the following example:

create table forums (
    forum_id int primary key,
    user_id int
);

create table comments (
    comment_id int primary key,
    forum_id int,
    constraint fk_comments_forum 
        foreign key (forum_id) 
        references forums(forum_id)
        on delete cascade
);

select * from forums;
FORUM_ID |用户身份 --------: | ------: 1 | 1 2 | 2
select * from comments;
COMMENT_ID |论坛ID ---------: | --------: 1 | 1 2 | 1 3 | 2
delete from forums where forum_id = 1;
1 rows affected

select * from comments;
COMMENT_ID |论坛ID ---------: | --------: 3 | 2

【讨论】:

【参考方案2】:

我不明白您为什么为此使用两个查询。逻辑似乎是:

BEGIN
   DELETE COMMENTS
   WHERE FORUMID = :OLD.forumID;
END;

【讨论】:

是的,你是对的,我想我已经重复了两次相同的操作。谢谢【参考方案3】:

您可以将其转换为 AFTER STATEMENT 触发器,然后可以删除行 -

CREATE OR REPLACE trigger trg_delete_comments
AFTER DELETE ON forum
BEGIN

   DELETE COMMENTS
   WHERE FORUMID IN (select forumID
                     from forum
                     where forumID = :OLD.forumID);
END;
/

【讨论】:

上述 after 语句将不起作用。 Old.column_name not New.column_name 列在语句级触发器中不可用。复合触发器,或者如果在您的版本上不可用,则可以使用一个包来模拟复合触发器。但是在 FK 上级联仍然比任何一个都容易得多。【参考方案4】:

我认为您可能在这里重新发明***。您可以简单地将外键定义为on delete cascade,然后让数据库为您完成繁重的工作:

ALTER TABLE comments
ADD CONSTRAINT fk_forum
FOREIGN KEY (forumid)
REFERENCES forum(forumid)
ON DELETE CASCADE

【讨论】:

以上是关于触发器从另一个表中删除行的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 删除触发器 - 引用已删除行或标记为删除的行的行句柄

从另一个表中查找触发

插入触发器 SQL。插入新表后如何从另一个表中检索值

oracle触发器在表中插入新行时更新新的视图行

将任何员工删除到员工表中时如何构建触发器以复制行

根据另一个表中的值删除行