第3章:复习篇——第5-1节:数据库编程1

目录

一、T-SQL语言编程基础

[1. 标识符与注释](#1. 标识符与注释)

(1)标识符

(2)注释

[2. 常量与变量](#2. 常量与变量)

(1)常量

(2)变量

[3. 运算符与表达式](#3. 运算符与表达式)

(1)算术运算符

(2)赋值运算符

(3)位运算符

(4)比较运算符

(5)逻辑运算符

(6)字符串连接运算符

(7)复合运算符

(8)运算符的优先级

[4. 批处理与流程控制语句](#4. 批处理与流程控制语句)

(1)批处理

(2)流程控制语句

二、函数

[1. 函数定义](#1. 函数定义)

[2. 系统内置函数](#2. 系统内置函数)

(1)聚合函数

(2)数学函数

(3)日期和时间函数

(4)字符串函数

3.用户自定义函数

(1)标量函数

(2)调用标量函数

(3)内嵌表值函数

(4)多语句表值函数

(5)删除用户定义函数

(6)实战训练

三、存储过程

[1. 系统存储过程](#1. 系统存储过程)

[2. 用户自定义存储过程](#2. 用户自定义存储过程)

[3. 存储过程的优点](#3. 存储过程的优点)

[4. 创建不带参数存储过程](#4. 创建不带参数存储过程)

[5. 调用存储过程](#5. 调用存储过程)

6.实战训练

7.创建带参数存储过程

[(1)使用 T-SQL 语句创建带参数存储过程语法格式如下](#(1)使用 T-SQL 语句创建带参数存储过程语法格式如下)

(2)带输入参数存储过程的执行方式

(3)带输出参数的存储过程的执行方式

8.实战训练

四、触发器

[1.DML 触发器](#1.DML 触发器)

[2.DDL 触发器](#2.DDL 触发器)

[(1)使用 T-SQL 语句创建 DML 触发器](#(1)使用 T-SQL 语句创建 DML 触发器)

[(2)使用 T-SQL 语句创建 DDL 触发器](#(2)使用 T-SQL 语句创建 DDL 触发器)

3.实战训练

4.修改触发器

[(1)DML 触发器](#(1)DML 触发器)

[(2)DDL 触发器](#(2)DDL 触发器)

5.删除触发器

6.重命名触发器

7.禁用触发器

[(1)DML 触发器](#(1)DML 触发器)

[(2)DDL 触发器](#(2)DDL 触发器)

8.启用触发器

[(1)DML 触发器](#(1)DML 触发器)

[(2)DDL 触发器](#(2)DDL 触发器)


一、T-SQL语言编程基础

1. 标识符与注释

(1)标识符

标识符用来标识服务器、数据库和数据库对象(例如表、视图、索引、触发器、过程、约束、规则等)。SQL Server 的标识符有两种:常规标识符和分隔标识符。

  • 常规标识符第一个字符必须是 26 个大小写英文字母(a-z、A-Z)、其他语言字母字符,或下划线(_)、@、#;不允许嵌入空格或其他特殊字符。
  • 分隔标识符 :用双引号""或方括号[]分隔不符合常规标识符定义的标识符(如含空格的A B需写为[A B])。

(2)注释

注释是对 SQL 代码的解释说明,服务器不执行注释,仅增强可读性。T-SQL 支持两种注释:

  • 多行注释 :用**/*...*/**包裹,例如:/* hello,SQL Server 2016数据库应用课程 */
  • 单行注释 :以**--**开头,作用到行结束,例如:-- 解释该语句内容

2. 常量与变量

(1)常量

常量(字面值 / 标量值)是程序运行中保持不变的量,分为字符串常量、整型常量、货币型常量、日期时间常量、全局唯一标识常量,格式由数据类型决定。

(2)变量

变量对应内存区域,具有名称和数据类型,值可变化,分为局部变量和全局变量:

  • 局部变量:用户自定义,用于保存特定类型数据,一般用于批处理、存储过程或触发器。
  • 全局变量 :系统声明和维护,记录服务器状态,名称以@@开头;用户不能创建或用SET修改其值。

3. 运算符与表达式

SQL Server 2016 常用运算符包括算术、赋值、位、比较、逻辑、字符串连接、复合运算符,通过运算符连接运算值构成表达式。

(1)算术运算符

对数字数据类型表达式执行运算,包括**+(加)、-(减)、*(乘)、/(除)、%(取模)**;+、-也可用于日期型数据、数字字符与数值类型数据运算。

(2)赋值运算符

即**=**,将数据值指派给特定对象。

(3)位运算符

对整型(或兼容类型)表达式执行位操作,规则如下:

(4)比较运算符

(5)逻辑运算符

(6)字符串连接运算符

+不仅是算术运算符,还可将多个字符串按顺序组合为一个字符串(称为 "字符串串联表达式"),结果为字符数据类型。

(7)复合运算符

(8)运算符的优先级


4. 批处理与流程控制语句

(1)批处理

批处理(简称 "批",Batch)是脚本中的一段 SQL 语句集,这些语句一起提交并作为一个组执行,批结束的符号是go命令。批量提交可节省系统开销。

(2)流程控制语句

通过流程控制语句可实现顺序、条件、循环三种基本程序结构,增强程序逻辑性与结构性。SQL Server 主要流程控制语句包括:

  • begin...end 语句:将多条 SQL 语句合并为一个语句块,作为整体执行(需同时执行多条语句时使用)。

  • if...else 语句:用于条件分支流程。若条件表达式为真,执行语句 1 / 语句块 1;否则执行语句 2 / 语句块 2。

  • print 语句:用于显示字符类数据内容,其他数据类型需先转换类型再使用;通常用于测试运行结果。




二、函数

1. 函数定义

函数是 T-SQL 提供的用以完成某种特定功能的程序。在 T-SQL 编程语言中,函数可分为系统内置函数用户定义函数

  • 系统内置函数是 SQL Server 自带的可以直接使用,包括常用的聚合函数、数学函数、字符串函数、日期时间函数等。
  • 用户定义函数是用户根据需要在数据库中自己定义的函数,是由一个或多个 T-SQL 语句组成的子程序,可以反复调用。

2. 系统内置函数

(1)聚合函数

聚合函数对一组数据执行计算并返回单一的值。除 COUNT 函数之外,聚合函数忽略空值。聚合函数经常与 SELECT 语句的 GROUP BY 子句一同使用,聚合函数只能在 SELECT 语句的选择列表(子查询或外部查询)、HAVING 子句中作为表达式使用。

查询score成绩表中的选课人次、期末成绩最高最低分

复制代码
USE SCC
SELECT COUNT(SNO) 选课人次 ,MAX(ENDSCORE) 期末成绩最高分 ,MIN(ENDSCORE) 期末成绩最低分
FROM SCORE

(2)数学函数

数学函数用于对数值表达式进行数学运算并返回运算结果,组成数值表达式的数据类型有 decimal、integer、float、real、money、smallint 和 tinyint。

返回1.00~4.00之间的数字的平方根

复制代码
declare @sv float
set @sv = 1.00
while @sv < 4.00
begin
  select SQRT(@sv)
  select @sv=@sv+1
end

(3)日期和时间函数

日期和时间函数可对日期和时间输入值执行操作,返回一个字符串、数字或日期和时间值。

复制代码
-- 显示当前系统日期和时间
SELECT GETDATE()

-- 显示系统当前的年份
SELECT DATEPART(YEAR,GETDATE())

-- 返回代表指定日期的指定日期部分的字符串
SELECT DATENAME(DAY,GETDATE())

-- 使用日期函数计算 2011-11-11 至现在有多少年
SELECT DATEDIFF(YY,'2011-11-11',GETDATE())

(4)字符串函数

字符串函数用于对字符串进行连接、截取等操作。

复制代码
-- 显示学生表中所有姓"李"的学生
SELECT * FROM STUDENT WHERE LEFT(SNAME,1)='李'

-- 指出"应用"2字在"计算机应用基础"中的位置
SELECT CHARINDEX('应用','计算机应用基础')

-- 计算"SHAANXI INSTITUTE OF TECHNOLOGY"的长度
SELECT LEN('SHAANXI INSTITUTE OF TECHNOLOGY')

-- 把字符串"例 题"中间的一个空格转换为4个空格
SELECT STUFF('例 题',2,1,SPACE(4))

-- 将字符串"数据库应用"重复两遍
SELECT REPLICATE('数据库应用',2)

3.用户自定义函数

根据用户定义函数的返回值,可分为标量函数表值函数;表值函数又可分为内嵌表值函数及多语句表值函数。

  • returns子句指定标量数据类型,函数为标量值函数,可通过多条 T-SQL 语句定义。
  • returns子句指定table,函数为表值函数。

(1)标量函数

若用户定义函数的返回值为标量值,称为标量函数。格式如下:

复制代码
CREATE FUNCTION [owner_name.]function_name -- 函数名部分
	([{@parameter_name [as] scalar_parameter_data_type [=default]} [,...n]]) -- 形参定义部分
RETURNS scalar_return_data_type -- 返回值类型
[as]
BEGIN
	function_body -- 函数体部分
	return scalar_expression -- 返回语句
END

(2)调用标量函数

调用用户定义的标量函数时,需提供 "所有者名。函数名" 的双部分名称,有两种调用方式:

  1. SELECT 语句调用 :语法为**所有者.函数名(实参1,...,实参n)**,实参可为局部变量或表达式。
  2. EXECUTE 语句调用 :语法为**所有者.函数名 实参1,...,实参n(实参与形参顺序一致),或所有者.函数名 形参名1=实参1,...,形参名n=实参n**(实参与形参顺序可不一致)。

【实战训练】在数据库中创建名为CalNum_5的用户定义函数,使新学分在原有基础上减 1,并绑定在Course表上。任务步骤:

  • 创建CalNum_5用户定义函数。

  • course表中新增renum_5列,与该函数绑定。

  • 执行查询语句测试结果。

    -- 创建标量函数CalNum_5
    CREATE FUNCTION CalNum_5 -- 名称
    (@X decimal(6,0)) -- 参数
    RETURNS decimal(6,0)
    AS
    BEGIN
    RETURN (@X-1) -- 变量名
    END
    GO

    -- 向Course表新增列ReNum_5并绑定函数
    ALTER TABLE Course
    ADD ReNum_5 AS dbo.CalNum_5(credit)
    GO

    -- 测试查询
    SELECT renum_5, credit
    FROM Course

(3)内嵌表值函数

  • 定义RETURNS子句仅含TABLE,表示返回一个表;函数体只有一个RETURN语句,通过SELECT语句返回内嵌表,其他参数项同标量函数。

  • 调用 :只能通过SELECT语句调用,调用时可仅使用函数名。

  • 格式如下:

    CREATE FUNCTION [owner_name.]function_name -- 定义函数名部分
    (@parameter_name scalar_parameter_data_type [,...n]) -- 形参定义部分
    RETURNS TABLE -- 返回值为表类型
    AS RETURN
    (SELECT 语句 ) -- 通过SELECT语句返回内嵌表

(4)多语句表值函数

定义时需先通过RETURNS @局部变量 TABLE <返回表的定义>指定返回表的结构,函数体包含多条 T-SQL 语句,最终通过RETURN返回表。

复制代码
CREATE FUNCTION [owner_name.]function_name
	(@parameter_name scalar_parameter_data_type [,...n])
RETURNS @局部变量 TABLE <返回表的定义>
AS
BEGIN
	函数体
	RETURN
END

(5)删除用户定义函数

语法格式:DROP FUNCTION [{owner_name.} function_name] [,...n]

  • owner_name:所有者名;
  • function_name:要删除的用户定义函数名称;
  • n:可指定多个函数同时删除。

(6)实战训练

在数据库中创建用户自定义函数SearchXuefen3,查询学分大于 2 分的课程信息。任务步骤:

  • 创建SearchXuefen3函数;

  • 定义参数@xuefen(输入参数)、局部变量@xuefeninfo(存放返回表)并定义表结构;

  • 函数体生成符合条件的课程信息表;

  • 调用函数测试结果。

    -- 方法1:内嵌表值函数实现

    -- 创建内嵌表值函数SearchXueFen3
    CREATE FUNCTION SearchXueFen3(@xuefen numeric(5,2))
    RETURNS table
    AS
    RETURN(
    select Cno,Cname,Teacher,Credit
    from course
    where Credit>@xuefen)
    go

    -- 调用函数查询学分大于2的课程
    SELECT * FROM SearchXueFen3(2)

    -- 方法2:多语句表值函数实现

    -- 创建多语句表值函数SearchXueFen3
    CREATE FUNCTION SearchXueFen3(@xuefen numeric(5,2))
    RETURNS @xuefeninfo table
    (
    cno nvarchar(50),
    cname nvarchar(50),
    teacher nvarchar(50),
    credit numeric(5,2)
    )
    AS
    BEGIN
    insert @xuefeninfo
    select Cno,Cname,Teacher,Credit
    from course
    where Credit>@xuefen
    return
    END
    go

    -- 调用函数查询学分大于2的课程
    SELECT * FROM SearchXueFen3(2)

使用 SSMS 修改函数SearchXuefen3,将 "查询大于某学分的课程信息" 改为 "查询小于某学分的课程信息"。

任务实施步骤:

  1. 启动对象资源管理器,依次展开 "数据库"→SCC→"可编程性"→"函数"→"表值函数" 节点;
  2. 右击dbo.SearchXueFen3,选择 "修改" 命令;
  3. 在打开的 SQL 代码窗口中修改函数。



三、存储过程

存储过程是利用 SQL 语句和流程控制语句编写的预编译程序,存储在数据库内,可以被客户端应用程序调用,并允许数据以参数形式在存储过程和应用程序间传递,使用存储过程可以提高工作效率,减少数据在网络上的传输量。在 SQL Server 中可以自定义存储过程,也可以使用系统内置的存储过程。

1. 系统存储过程

系统存储过程是由 SQL Server 提供的存储过程,在 "master" 数据库中创建并存储,可以作为命令执行各种操作。主要用来从系统表中获取信息,为系统管理员管理 SQL Server 提供帮助,为用户查看数据库对象提供方便。用户可从任何数据库中执行系统存储过程,而无需使用 "master" 数据库来限定该存储过程的名称。系统存储过程以 "sp_" 或 "xp_" 开头。

SQL Server 2016 服务器中许多的管理工作都是通过执行系统存储过程来完成的。一些系统存储过程只能由系统管理员使用,而有些系统存储过程则通过授权可以被其他用户所使用。例如:系统存储过程 sp_rename 可以用来更改当前数据库中用户创建对象的名称。


2. 用户自定义存储过程

自定义存储过程由用户编写,是指为了实现某一特定业务需求,创建的可重用代码段模块。用户存储过程可以接受输入参数、向客户端返回结果和信息、返回输出参数等。


3. 存储过程的优点

  • 存储过程只在创建时编译,以后每次执行时不需要重新编译,可以加快系统运行速度。
  • 使用存储过程可以完成所有的数据库操作,可以封装复杂的数据库操作,简化操作流程,例如对多个表的更新、删除等。
  • 存储过程可以增强代码的安全性,对于用户不能直接操作存储过程中引用的对象,SQL Server 2016 可以设定用户对指定存储过程的执行权限,确保数据库安全。并且存储过程的定义文本可以被加密,使用户不能查看其内容。
  • 存储过程的代码直接存放于数据库服务器中,通过存储过程名直接调用,并在服务器端运行,执行速度快,且在客户端与服务器的通信过程中,不会产生大量的 T-SQL 代码流量。
  • 存储过程可以在 SQL Server 启动时自动执行,而不必在系统启动后再进行手工操作,可以自动完成一些需要预先执行的任务。

4. 创建不带参数存储过程

在 SQL Server 2016 中,可以使用 T-SQL 语句或 SSMS 创建存储过程。

使用 CREATE PROCEDURE 语句创建不带参数存储过程语法格式如下:

复制代码
CREATE PROC[EDURE]
存储过程名 [; number]
AS T-SQL语句

5. 调用存储过程

存储过程需要调用才能执行,不论是用户自定义存储过程还是系统存储过程,都需要调用执行。SQL Server 中使用 EXECUTE 语句执行存储过程,EXECUTE 可以直接简写为 EXEC。语法格式如下:

复制代码
[{EXEC|EXECUTE}]
{   [@返回值变量 =]
    { 存储过程名 [; number]|@存储过程变量名 }
    [[@参数名 =]{参数值 |@参数变量名 [OUTPUT]|[DEFAULT]}]
    [,...n]
}

6.实战训练

1.创建查看 SCC 数据库中 Course 表数据的存储过程 SelectProc。

复制代码
USE SCC
GO
CREATE PROCEDURE SelectProc
AS
SELECT * FROM Course
GO

测试存储过程的执行情况,在第 2 步的语句后继续输入如下语句:

复制代码
EXEC SelectProc
GO

2.创建统计选课人次的存储过程 CountProc。

复制代码
USE SCC
go
CREATE PROCEDURE CountProc
WITH ENCRYPTION  -- 进行加密
AS
SELECT COUNT(*) AS 选课总人次 FROM Score
GO

测试存储过程的执行情况,输入如下语句,显示结果如图所示。

复制代码
EXEC CountProc
GO


3.创建临时存储过程#AddTestTableProc,用于在数据库 SCC 中创建一个表 Test,表的字段要求如下表所示:

在 "查询编辑器" 窗口中,输入以下语句:

复制代码
USE SCC
GO
-- 创建临时存储过程
CREATE PROCEDURE #AddTestTableProc
WITH ENCRYPTION
AS
  CREATE TABLE Test(
  TestNo nvarchar(20) not NULL PRIMARY KEY,
  TestName nvarchar(30),
  TestTime date,
  TestNumber int)
GO

测试存储过程的执行情况,在第 1 步的语句后继续输入如下语句:

复制代码
EXEC #AddTestTableProc
GO

存储过程名称前添加 "#" 或 "##" 前缀表示创建临时存储过程。其中 "#" 为前缀,表示本地临时存储过程,"##" 为前缀,表示全局临时存储过程。SQL Server 关闭后,这些临时存储过程将消失。
4.使用系统存储过程sp_help查看存储过程SelectProc基本信息。

复制代码
USE SCC
GO
EXEC sp_help SelectProc;
EXEC sp_help @objname=SelectProc
GO

7.创建带参数存储过程

存储过程的参数分为输入参数和输出参数两种。

(1)使用 T-SQL 语句创建带参数存储过程语法格式如下

复制代码
CREATE PROC[EDURE] [schema_name.] procedure_name [; number]
{@parameter data_type}
[VARYING] [=default] [OUT|OUTPUT] [READONLY]
[WITH<ENCRYPTION]|[RECOMPILE]|[EXECUTE AS Clause>] ]
[FOR REPLICATION]
AS <sql_statement>

存储过程 说明:

  • @parameter:用于指定存储过程的参数,可以声明一个或多个参数。
  • data_type:用于指定参数的数据类型。
  • VARYING:指定作为输出参数支持的结果集,仅适用于游标参数。
  • default:用于指定参数的默认值。
  • OUTPUT:指定参数是输出参数。
  • READONLY:指示不能在过程的主题中更新或修改参数。

(2)带输入参数存储过程的执行方式

执行带输入参数的存储过程时,SQL Server 提供了以下两种传递参数的方式:

  • 直接给出实际参数的值,当有多个实际参数时,给出的实参的顺序与创建存储过程的语句中的参数顺序应保持一致。即参数传递的顺序就是定义的顺序。
  • 使用 "@参数名 = 参数值" 的形式传递参数值,参数可以按照任意顺序传递值。

(3)带输出参数的存储过程的执行方式

执行带输出参数的存储过程时,为了接收存储过程执行的返回值,需要使用对应数量的变量来存放返回参数的值;同时在调用存储过程时,接收返回值的变量需要加上 OUTPUT 关键字声明。


8.实战训练

1.使用 T-SQL 在数据库 SCC 中创建存储过程SelectCourseProc,用于查询指定学分数的课程信息。

复制代码
USE SCC
GO
CREATE PROCEDURE SelectCourseProc
@credit FLOAT
AS
SELECT * FROM Course WHERE Credit=@credit
GO
EXEC SelectCourseProc 2;
EXEC SelectCourseProc @credit=2;
GO

2.创建一个存储过程SelectStuCourseProc,用于查询指定专业或指定班级的学生选课情况,查询结果要求显示学生的专业,班级,学号,姓名,所修课程名,最终成绩。要求查询条件中的专业和班级在未指定具体值的情况下,默认值分别是 "计算机网络技术" 专业和 "物联 3182" 班级。

复制代码
USE SCC;
GO
IF EXISTS(SELECT * FROM sys.objects WHERE
name='SelectStuCourseProc')
    DROP PROC SelectStuCourseProc
GO

CREATE PROCEDURE SelectStuCourseProc
@specialty nvarchar(30)='计算机网络技术',
@className nvarchar(30)='物联 3182'
AS
SELECT c.Specialty as 专业,c.ClassName as 班级,s.Sno as 学号,s.Sname as 姓名,
  co.Cname as 所修课程名,sc.EndScore as 最终成绩
  FROM Class c JOIN Student s ON c.ClassNo=s.ClassNo
  JOIN Score sc ON s.Sno=sc.Sno
  JOIN Course co ON sc.Cno=co.Cno
  WHERE c.Specialty=@specialty OR c.ClassName=@className
GO

USE SCC
GO
EXEC SelectStuCourseProc;
EXEC SelectStuCourseProc '软件技术','物联 3181';
EXEC SelectStuCourseProc '软件技术';
EXEC SelectStuCourseProc @className='网络 3182',@specialty='物联网应用技术';
GO

3.创建一个带输出参数的存储过程SelectStuCountProc,用于查询指定的课程名称选修的学生总数,并把查询结果返回给用户。

复制代码
USE SCC;
GO
CREATE PROCEDURE SelectStuCountProc
@cName NVARCHAR(30),
@stuCount INT OUTPUT
AS
SELECT @stuCount=COUNT(*)
  FROM Score sc JOIN Course co ON sc.Cno=co.Cno
  WHERE co.Cname=@cName
GO

USE SCC
GO
DECLARE @stuCount INT;
DECLARE @cName NVARCHAR(30)='数据库应用';
EXEC SelectStuCountProc @cName,@stuCount OUTPUT;
SELECT '选修课程《'+@cName+'》的有'+LTRIM(STR(@stuCount))+'人'
GO



四、触发器

触发器是一种特殊的存储过程,基于表 / 视图 / 服务器 / 数据库创建,满足一定条件时自动执行,不由用户直接调用。以保证数据库的完整性,正确性和安全性。

当触发器所保护的数据发生变化(INSERT、UPDATE、DELETE)或当服务器、数据库中发生数据定义(CREATE、ALTER、DROP)后,其自动运行以保证数据的完整性和正确性。通俗地说,用户对数据库或表进行了诸如 INSERT、UPDATE、DELETE、CREATE、ALTER、DROP 等操作时,SQL Server 就会自动执行触发器所事先定义好的语句。在 SQL Server2016 中拥有 DML 触发器和 DDL 触发器。

1.DML 触发器

DML 触发器是当数据库服务器对表或视图发出了 INSERT、UPDAE 和 DELETE 语句等数据操作语言(DML)事件时要执行的操作。DML 触发器包含了复杂的逻辑处理,并能够实现复杂的数据完整性约束,与其它约束相比较,其优点有:

  • 触发器自动执行。因此利用此机制可以监测用户在数据库中进行的操作。
  • DML 触发器可以由表触发,并操作多张表,因此可以进行相关表的级联操作。
  • 触发器的功能强大,可以实现比 CHECK 约束更复杂的数据完整性约束。例如 CHECK 约束不能够引用其它表的属性来完成完整性检查工作,但是触发器可以完成。
  • 触发器可以有数据修改前以及修改后的触发功能,用户可以根据不同的触发时点采用不同的触发语句。
  • 可以同时对 INSERT、UPDATE、DELETE 三种操作进行触发,并可以编写 T-SQL 语句实现同一个触发语句的多种分支执行。

DML 触发器根据触发时机,可以分为 2 种类型:

  • AFTER 触发器 ,此类的触发器只能定义在表上,不能在视图上创建。当执行操作成功后,才自动执行该触发器;假设操作执行失败,则不会激活触发器。若有多个 AFTER 触发器被定义在同一张表,可以使用sp_settriggerorder定义触发器触发的先后顺序。
  • INSTEAD OF 触发器,又称替代触发器,该类触发器会替代触发的操作并执行。即在执行 INSERT、UPDATE、DELETE 前,由 INSTEAD OF 触发器去替代此语句并执行。可在视图与表中定义,而每一个操作只能够定义一个 INSTEADOF 触发器。

2.DDL 触发器

DDL 触发器激活后的功能与 DML 相似,都是执行一段存储过程中的 T-SQL 语句,不相同的是激活事件。DDL 触发器并不会由表与视图的 UPDATE、INSERT、DELETE 等操作激活,DDL 触发器是由数据定义语言的语句触发激活,这些语句主要是由 CREATE、ALTER、DROP 开头的语句。其优点有:

  • 可以记录用户对数据库架构的更改或进行操作的事件。
  • 可以用于权限控制,防止普通用户修改数据库架构等操作。
  • 当用户对数据库架构进行更改时,可以通过 DDL 触发器对其作出响应。

(1)使用 T-SQL 语句创建 DML 触发器

语法格式如下:

复制代码
CREATE TRIGGER 触发器名
ON 表名 | 视图名
FOR | AFTER | INSTEAD OF [INSERT , DELETE ,UPDATE]
AS  T-SQL语句

参数说明:FOR | AFTER | INSTEAD OF,如果单指定关键字 FOR,则默认为 AFTER 关键字。AFTER 关键字表示指定的 SQL 语句全部都执行后才触发,且视图不能定义 AFTER 触发器。INSTEAD OF 关键字表示在指定的 SQL 语句执行前,将其替换为触发器的 T-SQL 语句进行执行。

(2)使用 T-SQL 语句创建 DDL 触发器

语法格式如下:

复制代码
CREATE TRIGGER 触发器名
ON ALL SERVER | DATABASE
FOR | AFTER event_type | event_group
AS T-SQL语句

参数说明:FOR | AFTER,DDL 触发器只能指定 FOR 或 AFTER 触发器,和 DML 触发器有相同的功能。但是 DDL 没有 INSTEAD OF 类型触发器。

event_type,执行之后将导致激发 DDL 触发器的 T-SQL 语言事件的名称。DDL 事件中列出了 DDL 触发器的有效事件。表 22-1 为常用的触发事件。


3.实战训练

【实战训练】创建 INSERT 触发器

具体要求:在数据库 SCC 的 Course 表上创建名为Insert_Course的触发器,向 Course 表插入数据时触发:

  • 若统计表CountTable不存在,则创建该表(含字段CourseCount(课程总数)、StudentCount(学生总数));

  • CountTable无记录,则插入初始值为 0 的记录;

  • 插入 Course 新记录后,更新CountTableCourseCount为当前 Course 表的课程总数。

    --创建一个触发器,当用户向表Course中添加新记录后触发
    CREATE TRIGGER Insert_Course
    ON Course
    AFTER INSERT
    AS
    BEGIN
    --先判断是否存在CountTable,如果不存在则创建该表
    IF NOT EXISTS(SELECT * FROM sys.objects WHERE name='CountTable')
    --创建包含课程总数和学生总数的表CountTable
    CREATE TABLE CountTable(courseCount INT DEFAULT 0,
    studentCount INT DEFAULT 0);
    DECLARE @courCount INT; --声明一个变量用于保存课程总数
    --获得Course表中课程总数
    SELECT @courCount=COUNT(*) FROM Course;
    --如果表CountTable表中没有记录,则插入一条记录,初始值为0
    IF NOT EXISTS(SELECT * FROM CountTable)
    INSERT INTO CountTable VALUES(0,0);
    --更新表CountTable中字段courseCount的值为刚获得的课程总数
    UPDATE CountTable SET courseCount=@courCount;
    END

在 SSMS 工具栏点击 "执行",提示 "命令已成功完成" 后,刷新 Course 表的触发器,可看到新增的Insert_Course

测试触发器

复制代码
SELECT COUNT(*) AS Course表课程数 FROM Course
INSERT INTO Course VALUES('c090','移动物联网开发','张宏',5.0,60,72)
SELECT COUNT(*) AS Course表课程数 FROM Course
SELECT * FROM CountTable
GO

选中语句执行,查看 Course 表课程数变化及CountTableCourseCount更新结果。
【实战训练】创建禁止插入记录触发器

具体要求:在数据库 SCC 的CountTable表上创建名为Forbid_Insert_CountTable的触发器,向CountTable插入数据时触发,提示 "不允许直接向该表插入记录,操作被禁止" 并回滚操作。

复制代码
USE SCC
GO
--创建一个触发器,在用户向表CountTable新增数据时被禁止
CREATE TRIGGER Forbid_Insert_CountTable
ON CountTable
AFTER INSERT
AS
BEGIN
    RAISERROR('不允许直接向该表插入记录,操作被禁止',1,1)
    ROLLBACK TRANSACTION --回滚事务,撤销插入操作
END
GO

测试触发器

复制代码
INSERT INTO CountTable VALUES(1,1)
GO

执行后会触发提示并撤销插入操作。


【实战训练】创建 DELETE 触发器

具体要求:在数据库 SCC 的 Course 表上创建名为Delete_Course的触发器,删除 Course 表数据时触发,执行查询删除表DELETED中的记录。

复制代码
USE SCC
GO
--创建一个DELETE触发器,用户删除表Course的数据时触发
CREATE TRIGGER Delete_Course
ON Course
AFTER DELETE
AS
BEGIN
    DECLARE @courCount INT; --声明一个变量用于保存课程总数
    --获得Course表中课程总数
    SELECT @courCount=COUNT(*) FROM Course;
    --更新表CountTable中字段courseCount的值为刚获得的课程总数
    UPDATE CountTable SET courseCount=@courCount;
    SELECT * FROM deleted
END 
GO

说明:DELETED表是触发器执行时自动创建的内存临时表,用于存储DELETE/UPDATE语句影响的行的副本;触发器执行完成后会被自动删除。

测试触发器

复制代码
DELETE FROM Course WHERE Cno='c090' --删除前面新增的记录
GO
SELECT * FROM CountTable
GO

【实战训练】创建 UPDATE 触发器

具体要求:在数据库 SCC 的Score表上创建名为Update_Score的触发器,更新Score表数据时触发,显示更新前后的记录。

复制代码
USE SCC
GO
--创建一个UPDATE触发器,用户更新表Score的数据时触发
CREATE TRIGGER Update_Score
ON Score
AFTER UPDATE
AS
BEGIN
    SELECT Sno,Cno,Uscore AS 更新前Uscore,EndScore AS 更新前EndScore
        FROM deleted
    SELECT Sno,Cno,Uscore AS 更新后Uscore,EndScore AS 更新后EndScore
        FROM inserted
END 
GO

说明inserted表是内存临时表,用于存储INSERT/UPDATE语句影响的行的副本(保存插入 / 更新后的记录);触发器执行完成后会被自动删除。

测试触发器

复制代码
UPDATE Score SET Uscore=85, EndScore=83
WHERE Cno='c017' and Sno='s032190124' --更新记录
GO
SELECT * FROM Score
GO

【实战训练】创建 DDL 数据库触发器

具体要求:在数据库 SCC 中创建作用域为数据库的 DDL 触发器trig_scc_del,删除表时触发,提示 "禁止删除表操作" 并回滚操作。

复制代码
USE SCC
GO
--创建一个DDL触发器,用户删除数据库中的表时触发
CREATE TRIGGER trig_scc_del
ON DATABASE
AFTER DROP_TABLE
AS
BEGIN
    PRINT '不能进行删除表的操作'
    ROLLBACK TRANSACTION
END
GO

测试触发器

复制代码
DROP TABLE test
GO

4.修改触发器

(1)DML 触发器

通过 T-SQL 语句修改触发器语法格式:

复制代码
ALTER TRIGGER 触发器名
ON 表名 | 视图名
FOR | AFTER | INSTEAD OF [INSERT , DELETE ,UPDATE]
AS  T-SQL语句

通过 SQL Server Management Studio 修改触发器操作步骤:启动 SSMS,在 "对象资源管理器" 中依次展开节点 "数据库"→"数据库名"→"表"→"表名"→"触发器"→"触发器名",双击触发器名即可编辑修改内容。

(2)DDL 触发器

通过 T-SQL 语句修改触发器语法格式:

复制代码
ALTER TRIGGER 触发器名
ON ALL SERVER | DATABASE
FOR | AFTER event_type | event_group
AS T-SQL语句

5.删除触发器

通过 T-SQL 语句删除触发器语法格式:

复制代码
DROP TRIGGER { 触发器名称 } [ ,...n ]

通过 SQL Server Management Studio 删除触发器操作:右键单击 "对象资源管理器" 中的 "触发器名",选择删除选项即可。


6.重命名触发器

通过存储过程sp_name完成,语法格式:

复制代码
[EXECUTE] sp_name 原触发器名, 新触发器名

7.禁用触发器

(1)DML 触发器

通过 T-SQL 语句禁用触发器

复制代码
DISABLE TRIGGER trigger_name ON table_name

通过 SQL Server Management Studio 禁用触发器操作:右键单击 "对象资源管理器" 中的 "触发器名",选择禁用选项即可。

(2)DDL 触发器

禁用语法:

复制代码
DISABLE TRIGGER 触发器名 | ALL ON DATABASE | ALL SERVER

8.启用触发器

(1)DML 触发器

通过 T-SQL 语句启用触发器

复制代码
ENABLE TRIGGER trigger_name ON table_name

通过 SQL Server Management Studio 启用触发器操作:右键单击 "对象资源管理器" 中的 "触发器名",选择启用选项即可。

(2)DDL 触发器
复制代码
ENABLE TRIGGER 触发器名 | ALL ON DATABASE | ALL SERVER
相关推荐
Mr.朱鹏2 小时前
分布式接口幂等性实战指南【完整版】
java·spring boot·分布式·sql·spring·云原生·幂等
一个天蝎座 白勺 程序猿2 小时前
破局困境:Oracle迁移金仓KingbaseES数据库的深度实践
数据库·sql·oracle·kingbase·kingbasees·金仓数据库
航Hang*2 小时前
第3章:复习篇——第6节:数据库安全管理与日常维护
数据库·笔记·sql·mysql
TG:@yunlaoda360 云老大2 小时前
华为云国际站代理商HiLens的技术优势体现在哪些方面?
服务器·数据库·华为云
Ashley_Amanda2 小时前
各种视图类型的创建方法和区别
数据库·oracle
zhoupenghui1682 小时前
项目访问接口时报“MISCONF Redis is configured to save RDB snapshots, ...“错误的解决方案
数据库·redis·mybatis
leaf9z2 小时前
麒麟系统V10 arm版部署Xtrabackup8
mysql
byzh_rc2 小时前
[模式识别-从入门到入土] 支持向量积SVM
数据库·人工智能·算法
程序员水自流2 小时前
MySQL常用SQL语法及参数详细介绍(新手经验书)
java·数据库·sql·mysql·oracle