前言:之前在学习SQL Server时接触过这个概念,但当时只是简单提及,而且也没有具体教学例子,因此只是对这个概念略知一二,今天接触到了,按照惯例我将讲解该知识点。
触发器:
触发器是SQL Server提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程。
触发器的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。
---百度百科
从概念上来看,触发器是一种存储过程,而它的执行需要事件来触发,作用是用来加强数据的完整性约束,这几点我们需要知道。
我们来结合牛腩视频的例子:
首先我们在类别表内添加类别,之后在新闻表添加属于某个类别的新闻,再在评论表中添加属于某条新闻的评论:
我们要增加一个删除类别的功能,而删除类别的同时需要将类别下的新闻也全部删掉,删掉新闻的同时也要将这些新闻下的评论都删掉(想想你在删掉某条说说的时候,是不是评论、点赞的信息都没有了)。这个功能如果我在D层只用以下代码来实现:
/// <summary>
/// 删除类别(连同其下的新闻及新闻评论一起删除)
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool Delete(string id)
{
bool flag = false;
string sql = "Delete from category where id=@id";
SqlParameter[] paras = new SqlParameter[]
{
new SqlParameter("@id",id)
};
int res = sqlhelper.ExecuteNonQuery(sql, paras);
if (res > 0)
{
flag = true;
}
return flag;
}
Web层:
//删除新闻
protected void Button4_Click(object sender, EventArgs e)
{
string catName = TextBox1.Text;
string id = TextBox2.Text;
Category cat = new Category(id, catName);
bool b = new CategoryDAO().Delete(id);//删除类别除功能
Response.Write(b);
GridView1.DataSource = new CategoryDAO().SelectAll();//取出当前所有新闻类
GridView1.DataBind();
}
得到的结果(由于还原案发现场有点麻烦,我就直接把错误打出来吧):
DELETE 语句与REFERENCE约束...冲突。该冲突发生于...
问题原因:我们在刚刚创建数据库的时候,在三个表之间建立了数据库关系图:
如果单单只删除类别表,而类别表下面有新闻存在,就会造成空数据的存在。SQL Server为了保证数据的完整性,不允许这种情况出现。
所以,我们需要建立触发器:
触发器语法:
USE [newssystem]
GO
/****** Object: Trigger [dbo].[trigCategoryDelete] Script Date: 2019/6/5 19:07:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: 任博扬
-- Create date: 2019-6-5,10:32
-- Description: 删除类别触发器
-- =============================================
ALTER TRIGGER [dbo].[trigCategoryDelete]
ON [dbo].[category]
--触发器代替了Delete操作
instead of DELETE
AS
BEGIN
declare @caId int
--从临时表中取出刚刚删除的类别
select @caId=id from deleted
--删除评论
delete comment where newsid in (select newsid from news where caID=@caId)
--删除新闻
delete news where caId=@caId
--删除类别
delete category where id=@caId
END
其中,instead of DELETE代表触发器代替原来的Delete语句;临时表deleted中存储刚刚删除的数据,可以用于查询;子查询不用多说,很好理解。
结果:(左上角的True代表操作正确执行)