数据库中的表都是通过主外键联系的,因此它们之间也就有了约束,所以当我们删除一条记录时,如果此条记录的主键是另一张表中的记录的外键时,那么就删除不了。视频中老师说有好几种办法,下面我说一下我了解的三种方法 。
第一种:将删除规则改为级联操作
1. 打开数据库中的数据库关系图
2. 修改 Insert和Update规范
首先点击两张表之间的关系,修改右边的删除规则为“级联”。这时再删除,就可以顺利删除了。
第二种:存储过程
这种方法也很简单,就是利用存储过程,不过删除语句有严格的顺序关系。比如新闻类别下有新闻,新闻下有评论,如果我们想删除一个新闻类别时,就要先删除评论,再删除新闻,最后才能删除新闻类别。
第三种:instead of 触发器
由于我之前对触发器接触的不深,所以这种方法对我来说也算是一个新知识。以前只用过 after 触发器,after触发器是在执行完某个动作之后才会自动触发的。而对于上述情况的话,如果用这种触发器就解决不了我们的问题,因为after触发器是删除完新闻类别触发的,但是我们现在无法删除新闻类别。
这时我们就可以利用 instead of 触发器,instead of 顾名思义就是“替代”的意思。这种触发器并不会执行实际的操作语句,而是用触发器执行的操作去替代实际要做的操作。
下面来看一个例子:
USE [newssystem]
GO
/****** Object: Trigger [dbo].[trig_category_delete] Script Date: 2019-01-06 20:53:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ======================================================
--Author: <Vijay>
--Create date: <2019-01-05 10:41>
--Description: 删除新闻类别触发器
-- ======================================================
ALTER TRIGGER [dbo].[trig_category_delete]
ON [dbo].[category]
INSTEAD OF DELETE
AS
BEGIN
declare @caId int
select @caId = id from deleted
--删除评论
delete from comment where newsId in (select newsId from news where caId = @caId)
--删除新闻
delete from news where caId = @caId
--删除新闻类别
delete from category where id=@caId
END
先介绍一下inserted表和deleted表,具体看下图。
看上面的代码,这是一个删除触发器,但是当我们从新闻类别表中删除一条记录时,并没有立即把它删除,而是先把要删除的记录存储在 deleted 这张临时表中,然后去执行 BEGIN 下面的 SQL 语句,这些语句也是有严格的删除顺序的,即先删除评论,再删除新闻,最后删除新闻类别。