资源简介 (共91张PPT)第八单元 数据库编程任务8.1 用户自定义函数任务8.2 创建存储过程任务8.3创建触发器8.1.1 情景描述8.1.2问题分析8.1.3 解决方案8.1.4 知识总结8.1.5 应用实践任务8.1 用户自定义函数学生信息管理系统里经常需要做一些重复性的操作,可把这些操作创建为函数来使用。数据库开发人员需要创建一个函数,要求该函数可以根据输入的专业名称,返回本专业学生的学号、姓名、性别、出生日期、身份证号。8.1.1 情景描述为了解决上述问题,需要完成以下任务:1.分析专业名称和学生信息之间的关联,先从专业名称,在专业表中查询出专业代码,再由专业代码,在班级表中查询出班级编号,最后根据班级编号,在学生表中查询出学生的信息。2.根据分析结果,写出创建函数的命令。3.执行函数以验证结果。8.1.2问题分析1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“学生管理”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:8.1.3 解决方案CREATE FUNCTION funstudent(@major varchar(32))RETURNS TABLEASRETURN(SELECT 学号,姓名,性别,出生日期,身份证号FROM 学生WHERE 班级编号 IN( SELECT 班级代码FROM 班级WHERE 专业代码 IN (SELECT 专业代码FROM 专业WHERE 专业名称=@major)))4.单击工具栏上的【执行】按钮,如图所示。5.在“查询编辑器”上输入语句“SELECT * FROM funstudent ('软件技术')”,单击工具栏上的【执行】按钮,即可查询软件技术专业的学生的信息。编程基础变量与常量IF…ELSE语句CASE 语句WHILE语句RETURN语句函数标量函数表值函数8.1.4 知识总结常量表示一个特定数据值的符号,在程序运行过程中始终保持不变,常量的格式取决于它所表示的值的数据类型,如字符常量必须用单引号括起来,由字母、数字及其它特殊字符组成;二进制常量由0、1构成;十进制整型常量不带小数点;日期常量也要用括号括起来等。在程序运行过程中,值可以改变的量称为变量,按照变量的有效作用范围,可以分为局部变量和全局变量。局部变量的作用范围仅限于程序内部,局部变量名必须使用@符号开始。全局变量的作用范围不仅仅局限于某一程序,任何程序均可以随时访问,全局变量经常存储一些SQL Server的配置设定和统计数据,不能由用户的程序定义,全局变量以符号@@开始。变量与常量局部变量用关键字DECLARE声明,语法格式如下:DECLARE @变量名 数据类型参数说明如下:@变量名:局部变量的名称,必须使用@符号开始,变量名遵守标识符的命名规则。数据类型:用于指定局部变量的数据类型,可以是由系统提供的除了text、ntext、image之外的数据类型。变量声明局部变量一旦声明,初始值默认为NULL,可以使用SET或SELECT命令为变量赋值,语法格式如下:SET @变量名=表达式 或者SELECT @变量名=表达式参数说明如下:@变量名:指定已经声明的要被赋值的变量名称。表达式:合法的有效的SQL SERVER表达式。变量的赋值变量的值或常量的值可以通过SELECT或PRINT命令输出,语法格式如下:SELECT 局部变量|全局变量|常量PRINT 局部变量|全局变量|常量参数说明如下:@变量名:不加单引号。常量:如果是字符串要用括号括起来,如果是多个字符串的连接,需要用+号连接。变量的输出【例8-1】定义一个字符串变量和整型变量,为其赋值,并输出查看结果。DECLARE @course varchar(64),@a intSELECT @course as '@course赋值前的值' ,@a as '@a赋值前的值'SELECT @course ='sql server基础',@a=1SELECT @course as '@course赋值后的值' ,@a as '@a赋值后的值'SELECT '欢迎大家学习'+@course①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。SELECT @@SERVERNAME AS '服务器名' , @@VERSION AS '版本'【例8-2】显示当前服务器的名称及版本。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。条件判断语句IF…ELSE用来判断当一个条件成立时执行某段程序,条件不成立时执行另外一段程序。语法格式如下:IF 条件表达式语句块1ELSE语句块2参数说明如下:条件表达式:关系运算符和逻辑运算符组成的表达式,其值决定分支的执行路线。语句块1:条件表达式成立时,执行的语句块,如果语句块的语句多于一条,语句块前用BEGIN,语句块后用END。语句块2:条件表达式不成立时,执行的语句块。ELSE语句块2:可选项,最简单的IF语句没有ELSE选项。IF…ELSE语句DECLARE @price moneySET @price =66IF @price>50PRINT '价格过高'ELSEPRINT '价格比较合适'【例8-3】IF…ELSE语句的用法,IF语句成立执行的语句只有一条。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。DECLARE @score floatSET @score =50IF @score<60BEGINSET @score=@score +20PRINT @scoreENDELSEBEGINSET @score =@score+10PRINT @scoreEND【例8-4】IF…ELSE语句的用法,IF语句成立时执行的语句多于一条。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。当条件表达式的分支多于两条的时候,可以用CASE语句对每一种结果处理。语法格式如下:CASE 条件表达式WHEN 条件表达式结果1 THEN 语句1WHEN 条件表达式结果2 THEN 语句2……WHEN 条件表达式结果n THEN 语句nELSE 语句n+1END参数说明如下:条件表达式:关系运算符和逻辑运算符组成的表达式,其值决定分支的执行路线。条件表达式结果:要与条件表达式的数据类型相同,二者如果相同,则执行对应THEN后面的语句。ELSE:与上面的条件表达式结果都不相同的时候,执行ELSE后面的语句。CASE 语句CASE语句执行的步骤如下:①计算条件表达式的值,然后按照指定顺序对每个WHEN子句的条件表达式结果进行比较。②一旦发现条件表达式和条件表达式结果相同,则返回对应THEN后面的语句的执行结果。③如果条件表达式和条件表达式结果都不能匹配,则返回ELSE后面的语句的执行结果。DECLARE @score intSET @score=85SELECTCASE @score/10when 10 then '满分'when 9 then '优秀'when 8 then '良好'when 7 then '中等'when 6 then '及格'else '不及格'ENDAS '五级制成绩'【例8-5】定义一个变量,赋值百分制成绩,改为五级制成绩输出。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。WHILE语句可以根据某一条件重复执行一段代码,直到不满足特定条件为止,WHILE语句有两个关键部分,循环条件和循环语句,当循环条件为真,就执行循环体,循环体执行结束就去判断循环条件,如果循环条件继续为真,则重复执行循环体,一直到循环条件为假为止。语法格式如下:WHILE 循环条件循环体参数说明如下:循环条件:关系运算符和逻辑运算符组成的表达式,其值循环体是否执行。循环体:循环条件为真重复执行的有效的SQL语句。如果循环体的语句多于一条,则循环体要用BEGIN…END括起来。在循环体内可以使用BREAK语句无条件终止循环体的执行;也可以使用CONTINUE语句提前结束本次循环,直接进入下一次循环条件的判断。WHILE语句SELECT 教师编号,教师姓名,CASE 职称WHEN '教授' THEN '高级'WHEN '副教授' THEN '高级'WHEN '讲师' THEN '中级'WHEN '助教' THEN '初级'ENDAS '教师职称'FROM 教师【例8-6】在“学生管理”数据库里查询教师编号、教师姓名、教师职称,其中教师职称用高级、中级、初级表示。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。DECLARE @i int ,@sum intSET @i =1SET @sum=0WHILE @i<=100BEGINSET @sum=@sum+@iSET @i=@i+1ENDPRINT '循环结束后,变量@i的值是:'+str(@i)PRINT '循环结束后,变量@sum的值是:'+str(@sum)【例8-7】计算1到100的和。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。DECLARE @i int,@a int,@b int ,@c intSET @i =101WHILE @i<=999BEGINSET @a =@i/100SET @b=@i/10%10SET @c =@i%10IF @a*@a*@a +@b*@b*@b+@c*@c*@c =@iBEGINPRINT '找到的第一个水仙花数:'+str(@i)breakENDSET @i=@i+1END【例8-8】水仙花数是一个三位数,满足:个位数的立方、十位数的立方及百位数的立方三者之和等于此三位数本身。求从101开始的第一个水仙花数。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。DECLARE @i int ,@sum intSET @i =1SET @sum=0WHILE @i<100BEGINSET @i=@i+1IF @i%2=0continueSET @sum=@sum+@iENDPRINT '1到的奇数之和是:'+str(@sum)【例8-9】求1到100的奇数之和。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。RETURN语句主要用于无条件的终止当前SQL语句的的执行,可用于存储过程、函数等语句中。RETURN语句函数可以完成一个特定功能,常用系统函数的用法在前面已经学习过,它们只能解决特定问题,无法根据实际需要进行调整,用户可以根据需要创建自定义函数,以实现特殊的功能。在SQL Server中,根据函数的返回值的形式将用户函数分为两大类,分别是标量函数和表值函数,其中表值函数又被分为内嵌表值函数和多语句表值函数。函数如果函数返回值是标量数据类型,则函数为标量函数,标量函数创建完成后,可以像使用系统函数一样去调用。使用CREATE FUNCTION创建自定义标量函数的语法格式如下:CREATE FUNCTION 函数名(形式参数列表)RETURNS 返回值类型ASBEGIN函数体END参数说明如下:函数名:指定自定义函数的名称,遵守标识符的命名规则。形式参数列表:格式为“变量名 数据类型”,参数之间用逗号分隔。返回值类型:函数运行结束时使用RETURN语句返回值的类型,可以是除了text、ntext、image和timestamp之外的基本数据类型。函数体:合法的SQL语句,必须包含RETURN语句,RETURN语句返回值的数据类型和RETURNS子句指定的返回值类型要一致。标量函数CREATE FUNCTION funscore()RETURNS decimal(5,2)ASBEGINRETURN (SELECT 成绩FROM 选课WHERE 学号=6 AND 课程编号=2)END【例8-10】创建一个函数名为funscore,求出学号为6、选修的课程编号为2的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT dbo.funscore()”,单击工具栏上的【执行】按钮,得出成绩信息。说明:函数如果没有参数,函数名后面的小括号也不能省略;在第二行用RETURNS关键字指出函数运行结束后返回的值的数据类型是decimal(5,2),那么在函数体内需要用RETURN语句返回一个此类型的值;标量函数的调用方法和系统函数相同;此函数没有参数,功能限制为只能返回学号为6的学生选修课程编号为2的成绩,其它的学生的成绩不能用此函数,可以通过创建有参数的函数来解决。CREATE FUNCTION funscorenew(@stuid int,@courseid int)RETURNS decimal(5,2)ASBEGINRETURN ( SELECT 成绩FROM 选课WHERE 学号=@stuid AND 课程编号=@courseid)END【例8-11】创建一个函数名为funscorenew,输入学号和课程编号,返回指定学号和课程编号的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“函数”,展开“标量值函数”,可以看到创建的函数前面加了所有者dbo,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT dbo.funscorenew(1,1)”,单击工具栏上的【执行】按钮,得出学号为1的学生选修的课程编号为1的成绩。说明:函数的参数先写参数名,再写参数的数据类型;函数的运行在SELECT语句中,要指出函数的实际参数值,实际参数值要和形式参数一一对应。每次运行函数,输入的实际参数不同,得出的形式参数也不同。CREATE FUNCTION funclass(@classid int)RETURNS intASBEGINRETURN(SELECT COUNT(*)FROM 学生WHERE 班级编号=@classid)END【例8-12】创建一个函数名为funclass,输入班级编号,统计班级的学生人数。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“函数”,展开“标量值函数”,可以看到创建的函数前面加了所有者dbo,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT dbo.funclass(3)”,单击工具栏上的【执行】按钮,得出班级编号为3的学生人数。如果函数返回值是表(TABLE),则函数为表值函数,表值函数返回的结果是表,因此,表值函数的调用要放在SELECT语句的FROM子句调用,使用CREATE FUNCTION创建内嵌表值函数的语法格式如下:CREATE FUNCTION 函数名(形式参数列表)RETURNS TABLEASRETURN(SELECT语句)参数说明如下:TABLE:指定函数返回值的类型为表。SELECT语句:单条select查询语句,查询语句的结果做为函数返回的表。表值函数CREATE FUNCTION funteacher(@deptname varchar(50))RETURNS tableASRETURN( SELECT 教师编号,教师姓名,性别,职称,学历,学位,专业FROM 教师 AS a JOIN 系部 AS bON a.系部代码=b.系部代码WHERE 系部名称=@deptname)【例8-13】创建一个函数名为funteacher,输入系部名称,查询指定系部的教师的编号、姓名、性别、职称、学历、学位、专业信息。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“函数”,展开“表值函数”,可以看到创建的函数前面加了所有者dbo,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT * FROM funteacher('电子系')”,单击工具栏上的【执行】按钮,查询电子系的教师的信息。说明:函数的参数的数据类型要和数据库中系部表的字段“系部名称”的数据类型相同;返回的结果是表,SELECT语句查询的结果就是表的格式,当作函数的结果。CREATE FUNCTION funstuscore(@stuid int=1)RETURNS TABLEASRETURN(SELECT xs.学号,姓名,性别,xk.课程编号,课程名称,成绩FROM 学生 AS xs JOIN 选课 AS xk ON xs.学号=xk.学号JOIN 课程 AS kc ON kc.课程编号=xk.课程编号WHERE xs.学号=@stuid)【例8-14】创建一个函数名为funstuscore,输入学号,查询指定学生的选课信息。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“函数”,展开“表值函数”,可以看到表值函数dbo.funstuscore,查看其参数,@stuid有默认值,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT * FROM funstuscore (DEFAULT)”,单击工具栏上的【执行】按钮,可查询学号为默认值1的选课信息,参数DEFAULT也可以换成指定的学号。说明:在创建函数的时候,可以指定默认值。当函数定义需要修改的时候,使用ALTER FUNCTION命令,修改函数的的语法与创建函数的语法一样,只需要将CREATE换成ALTER即可,但是不能修改自定义函数的类型,即不能将标量函数更改为内联表值函数或者多语句表值函数。修改函数ALTER FUNCTION funscore()RETURNS decimal(5,2)ASBEGINRETURN (SELECT 成绩FROM 选课WHERE 学号=5 AND 课程编号=1)END【例8-15】修改已经存在的函数为funscore,更改为查询学号为5,选修的课程编号为1的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT dbo.funscore( )”,单击工具栏上的【执行】按钮,得出固定的学号为5的学生选修的课程编号为1的成绩。说明:在修改函数的时候,可以修改函数的定义,但是如果更改函数返回值的类型,就会产生错误,即如果把函数返回值的类型decimal(5,2)更改为TABLE类型,则会产生错误。可以使用DROP FUNCTION命令删除自定义函数,语法格式如下:DROP FUNCTION 函数名删除用户自定义函数DROP FUNCTION funstuscore【例8-16】删除函数funscore。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入语句“SELECT dbo.funscore( )”,单击工具栏上的【执行】按钮,服务器会报错。在销售数据库中,创建一个函数funproduction,根据输入的顾客编号,查询顾客购买的商品编号,商品名称,数量,价格,总价,商品类别。1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“销售”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:8.1.5 应用实践CREATE FUNCTION funproduction(@customerid varchar(50))RETURNS TABLEASRETURN(SELECT sp.商品ID,名称,类别名称,数量,价格,总价FROM 商品 AS sp JOIN 商品类型 AS splxON sp.类别ID=splx.类别IDJOIN 销售 AS xs ON xs.商品ID=sp.商品IDWHERE 顾客ID=@customerid)4.单击工具栏上的【执行】按钮,如图所示。5.在“查询编辑器”上输入语句“SELECT * FROM funproduction(2)”,单击工具栏上的【执行】按钮,查询顾客编号为2的顾客购买的商品信息。8.2.1 情景描述8.2.2问题分析8.2.3 解决方案8.2.4 知识总结8.2.5 应用实践任务8.2 创建存储过程根据学生信息管理系统的需求,数据库的开发人员需要创建一个存储过程,根据输入的职称,统计这类职称的教师人数,同时返回教师的编号、姓名、性别、职称、学历、系部名称的具体信息。8.2.1 情景描述为了解决上述问题,需要完成以下任务:1.写出统计指定职称的查询语句;2.写出查询指定职称的教师信息的语句;3.写出创建存储过程的语句;4.调用存储过程以验证结果。8.2.2问题分析8.2.3 解决方案CREATE PROC procteachercount @title varchar(20),@c int OUTPUTASBEGINSELECT @c=COUNT(*)FROM 教师WHERE 职称=@titleSELECT 教师编号,教师姓名,性别,职称,学历,系部名称FROM 教师 JOIN 系部 ON 教师.系部代码=系部.系部代码WHERE 职称=@titleEND1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“学生管理”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:4.单击工具栏上的【执行】按钮,如图所示。5.在“查询编辑器” 输入以下语句之后,单击工具栏上的【执行】按钮,在结果栏的“消息”选项卡内返回查询结果影响的行数,及统计的指定职称的人数。在结果选项卡中返回指定职称的教师信息。DECLARE @count intEXEC procteachercount '副教授',@count outputPRINT @count存储过程的概念引入存储过程的好处存储过程的创建和调用修改存储过程删除用户自定义存储过程查看存储过程信息重命名存储过程8.2.4 知识总结数据库中保存的预先编译好的独立的数据库对象,驻留在数据库中,可以被应用程序调用,并允许数据以参数的形式在过程与应用程序之间传递。能接收输入参数的值,存储过程的定义都包含对数据库进行查询修改的SQL语句,有返回值;它的返回值只是指明执行知否成功,不能返回用户需要的结果;存储过程不能直接在表达式中使用,可以带多个输出参数。存储过程主要分为三类,系统存储过程,扩展存储过程和用户自定义的存储过程。存储过程的概念存储过程在服务器端运行,执行速度快,存储过程创建好后被编译成可执行的系统代码保留在服务器中,一般用户只需要提供存储过程所需的参数,执行存储过程,就能得到所需的查询结果,而不用管具体的实现过程;存储过程存储在服务器上并在服务器上执行,网络上只传送存储过程执行的最终数据,可以减少网络流量;存储过程一旦创建,可以多次被用户调用,而不必重新编写SQL语句,实现了模块化程序设计的思想;存储过程如果需要修改,在修改之后,所有调用该存储过程的程序得到的结果都会随之改变,提高了程序的可移植性;用户可以被授予权限执行存储过程,而不必拥有访问存储过程中引用的表的权限,即当用户需要访问表中数据但是没有权限的时候,可以设计一个存储过程来存取表中的数据,提供给用户,存储过程只作为一个存取通道,保护了数据的安全性。引入存储过程的好处存储过程和表、视图等数据库对象一样,在使用前要先创建,使用CREATE PROCEDURE语句创建存储过程的语法格式如下:存储过程的创建和调用CREATE PROCEDURE 存储过程名 参数列表WITH ENCRYPTION ASBEGINSQL语句END参数说明如下:存储过程名:指定存储过程的名称,遵守标识符的命名规则,建议前缀加proc。参数列表:可以省略,格式为“参数名 数据类型”,参数之间用逗号分隔,参数可以指定默认值,格式为 “参数名 数据类型=默认值”,如果是输出参数,格式为“参数名 数据类型 OUTPUT”。WITH ENCRYPTION:用于加密存储过程定义语句的文本。SQL语句:合法的SQL语句,用于定义存储过程执行的操作。如果存储过程的定义只有一条SQL语句,那么BEGIN…END可以省略。存储过程创建成功后,使用EXECUTE命令执行存储过程,EXECUTE可以省略为EXEC。CREATE PROCEDURE procscoreASBEGINSELECT 成绩FROM 选课WHERE 学号=6 AND 课程编号=2END【例8-17】创建存储过程procscore,查询学号为6、选修的课程编号为2的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入语句“EXEC procscore”,单击工具栏上的【执行】按钮,查询固定的学号为6的学生选修的课程编号为2的成绩。说明:存储过程的定义只有一条SQL语句,此例中BEGIN…END可以省略。EXEC是关键字EXECUTE的简写。执行存储过程的时候,如果一次只执行一条语句,那么EXEC也可以省略。CREATE PROC procscorenew @stuid int,@courseid intASSELECT 成绩FROM 选课WHERE 学号=@stuid AND 课程编号=@courseid【例8-18】创建一个存储过程名为procscorenew,输入学号和课程编号,查询指定学号和课程编号的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“存储过程”,可以看到创建的存储过程前面加了所有者dbo,运行结果如图所示。③在“查询编辑器”上输入语句“procscorenew 1,1”,单击工具栏上的【执行】按钮,得出学号为1的学生选修的课程编号为1的成绩。说明:PROC是关键字PROCEDURE的简写形式;存储过程只用了一条SQL语句,BEGIN…END可以省略;存储过程的执行只有一条语句,EXEC可以省略;实际参数和存储过程定义指定的参数要一一对应。CREATE PROC procclass @classid int=1ASSELECT COUNT(*)FROM 学生WHERE 班级编号=@classid【例8-19】创建一个存储过程名为procclass,输入班级编号,查询指定班级的学生个数。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,展开“对象资源管理器”窗口的“学生管理”数据库下的“可编程性”文件夹,双击“存储过程”,可以看到创建的存储过程前面加了所有者dbo,运行结果如图所示。③在“查询编辑器”上输入语句“procclass”,单击工具栏上的【执行】按钮,显示班级编号为默认值1的学生个数。说明:PROC是关键字PROCEDURE的简写形式;存储过程的执行也可以用EXEC procclass;存储过程的定义有一个参数,在执行的过程中如果没有指定参数值,则用默认的参数值,也可以指定班级编号。CREATE PROCEDURE procteacher @deptname varchar(50)WITH ENCRYPTIONASSELECT 教师编号,教师姓名,性别,职称,学历,学位,专业FROM 教师 AS a JOIN 系部 AS b ON a.系部代码=b.系部代码WHERE 系部名称=@deptname【例8-20】创建一个存储过程名为procteacher,输入系部名称,查询指定系部的教师编号、教师姓名、性别、职称、学历、学位、专业。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入语句“procteacher '计算机系'”,单击工具栏上的【执行】按钮,显示计算机系的老师信息。CREATE PROC procsum @n int ,@sum int OUTPUTASBEGINDECLARE @i intSET @i=1SET @sum =0WHILE @i<=@nBEGINSET @sum=@sum+@iSET @i=@i+1ENDENDDECLARE @sum intEXEC procsum 100,@sum outputPRINT @sum【例8-21】创建一个存储过程名为procsum,输入一个数n,计算从1到输入的数n的和。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入以下语句之后,单击工具栏上的【执行】按钮,计算出从1到输入参数100的和。CREATE PROC procscorecourse @courseid int,@maxscore numeric(5,2) OUTPUT,@minscore numeric(5,2) OUTPUT,@avgscore numeric(5,2) OUTPUTASBEGINSELECT @maxscore=MAX(成绩),@minscore=MIN(成绩),@avgscore=AVG(成绩)FROM 选课WHERE 课程编号=@courseidSELECT 学生.学号,姓名,性别,身份证号FROM 学生 JOIN 选课 ON 学生.学号=选课.学号WHERE成绩<@avgscoreENDDECLARE @max numeric(5,2),@min numeric(5,2),@avg numeric(5,2)EXEC procscorecourse 1,@max output,@min output,@avg outputPRINT '最高分:'+CONVERT(VARCHAR(5),@max)PRINT '最低分:'+CONVERT(VARCHAR(5),@min)PRINT '平均分:'+CONVERT(VARCHAR(5),@avg)【例8-22】创建一个存储过程名为procscorecourse,输入课程编号,查询指定课程编号的课程的最高成绩,最低成绩,平均成绩,并查询成绩低于指定课程平均分的学生的学号,姓名,性别,身份证号。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。③在“查询编辑器”上输入以下语句之后,单击工具栏上的【执行】按钮,在结果栏的“消息”选项卡内返回查询结果影响的行数,及最高成绩,最低成绩,平均成绩。在结果选项卡中返回的小于平均成绩的学生的信息。当存储过程的定义需要修改的时候,使用ALTER PROCEDURE命令,修改存储过程的语法与创建存储过程的语法一样,只需要将CREATE换成ALTER即可。修改存储过程ALTER PROCEDURE procscoreASBEGINSELECT 成绩FROM 选课WHERE 学号=5 AND 课程编号=1END【例8-23】修改已经存在的存储过程名为procscore,更改为查询学号为5,选修的课程编号为1的成绩。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮。③在“查询编辑器”上输入语句“procscore”,单击工具栏上的【执行】按钮,查询固定的学号为5的学生选修的课程编号为1的成绩。可以使用DROP PROCEDURE命令删除自定义存储过程,语法格式为:删除用户自定义存储过程DROP PROCEDURE 存储过程名DROP PROCEDURE procscore【例8-24】删除存储过程procscore。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮。③在“查询编辑器”上输入语句“procscore”,单击工具栏上的【执行】按钮,则会提示找不到存储过程procscore。可以使用系统存储过程sp_help 查看存储过程的基本信息;用sp_helptext存储过程的定义信息,用法和查看视图信息相同。查看存储过程信息sp_help procscorecourse【例8-25】用sp_help查看存储过程procscorecourse的基本信息。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。sp_helptext procscorecourse【例8-26】用sp_helptext查看存储过程procscorecourse的定义文本。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。sp_helptext procteacher【例8-27】用sp_helptext查看加密存储过程procteacher的定义文本。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。可以使用sp_rename来对存储过程进行改名,语法格式如下:重命名存储过程sp_rename 存储过程原名 , 存储过程新名称参数说明如下:存储过程原名:指定数据库中存在的存储过程的名称。存储过程新名称:指定存储过程更改名称后的名称。sp_rename procteacher,procteachernew【例8-28】用sp_rename更改存储过程procteacher为procteachernew。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,运行结果如图所示。在销售数据库中,创建一个存储过程,根据输入的供应商名称,统计从该供应商进货的商品数量,并查询从该供应商进货的商品的编号,名称,价格,保质期。1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“销售”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:8.2.5 应用实践CREATE PROC procproduct @supplyname varchar(50),@c int OUTPUTASBEGINSELECT @c=COUNT(*)FROM 进货WHERE 供应商ID=(SELECT 供应商IDFROM 供应商WHERE 名称=@supplyname)SELECT 商品.商品ID ,商品.名称 ,商品.价格 ,商品.保质期FROM 商品 JOIN 进货 ON 商品.商品ID=进货.商品IDJOIN 供应商 ON 供应商.供应商ID=进货.供应商IDAND 供应商.名称=@supplynameEND4.单击工具栏上的【执行】按钮,如图所示。DECLARE @count intEXEC procproduct '重庆渝州服装厂',@count outputPRINT @count5.在“查询编辑器”上输入以下语句之后,单击工具栏上的【执行】按钮,在结果栏的“消息”选项卡内返回查询结果影响的行数,及从指定供应商进货的商品的个数。在结果选项卡中返回从指定供应商的进货的商品信息。8.3.1 情景描述8.3.2问题分析8.3.3 解决方案8.3.4 知识总结8.3.5 应用实践任务8.3创建触发器在班级表中,用专业代码存储班级所在的专业信息,但是专业代码在班级表中并没有被设置外键,以关联专业表的专业代码字段。这样在班级表中插入记录的时候,很容易保存一条不存在的专业代码的班级信息。数据库开发人员经过分析得出两种方案,一是需要修改专业表,增加专业代码的外键关联;二是在专业表中创建一个触发器来完成。经过考虑,数据库开发人员采用第二种方案。8.3.1 情景描述为了解决上述问题,需要完成以下任务:1.在班级表中创建一个插入触发器;2.在班级表中执行插入操作,激活触发器,验证触发器的工作。8.3.2问题分析1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“学生管理”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:8.3.3 解决方案CREATE TRIGGER triclassinsertON 班级 AFTER INSERTASBEGINIF (select 专业代码 FROM inserted) NOT IN (SELECT 专业代码 FROM 专业)BEGINPRINT '你要插入的班级信息的专业代码在专业表中不存在!'ROLLBACKENDEND4.单击工具栏上的【执行】按钮,提示“命令成功完成”,在对象资源管理器窗口的“班级”表下的“触发器”文件夹,可以看到创建的触发器。5.在“查询编辑器” 输入以下语句之后,单击工具栏上的【执行】按钮,激活触发器,执行结果如图所示。INSERT INTO 班级 VALUES(8,’计算机1403’,8, ’2014级’,’张静’,’互联网’)6.在“查询编辑器” 输入语句“SELECT * FROM 班级 WHERE 班级代码=8”之后,单击工具栏上的【执行】按钮,查询结果为空,则刚才的插入操作被撤销执行。触发器的概念触发器的分类触发器的作用DDL触发器的创建与管理DML触发器的创建与管理8.3.4 知识总结触发器和存储过程一样,是一组T-SQL语句的集合,是一种特殊的存储过程,作为表的一部分被创建,当向表中插入、更新或删除记录的时候自动执行,不能像存储过程一样由用户调用执行,只要触发器触发的条件满足,就会自动触发执行。触发器一旦运行,就会产生两个临时表,即已插入表(inserted)和已删除表(deleted),这两个临时表存储在内存中,由系统管理,用户不能执行插入、更新和删除操作,只能执行查询操作;表的结构与该触发器所在的表是相同的,具有相同的列名和列的定义。当触发器工作完成后,这两张临时表也会被删除。触发器的概念根据触发器触发的事件的不同,可以把触发器分为两大类型,即DML(数据修改语言)触发器和DDL触发器(数据定义语言)。DML触发器根据具体触发的语句,又分为INSERT触发器,UPDATE触发器和DELETE触发器。根据触发器触发的方式不同,可以把触发器分为后触发器(AFTER触发器)和替代触发器(INSTEAD OF触发器)。触发器的分类保持数据同步能够对表中的数据进行级联修改触发器可以实现比CHECK约束更为复杂的约束防止非法修改数据触发器的作用创建DDL触发器修改DDL触发器删除DDL触发器DDL触发器的创建与管理使用CREATE TRIGGER命令创建DDL触发器的语法规则如下:创建DDL触发器CREATE TRIGGER 触发器名ON ALLSERVER|DATABASEAFTER|FOR 操作ASBEGINSQL语句END参数说明如下:触发器名:指定定义的触发器名称,遵守标识符的命名规则,但不能以#或##开头,建议前缀加tri。ALLSERVER|DATABASE:指定触发器的作用域,ALLSERVER指触发器应用于整个服务器,DATABASE指触发器作用于当前数据库,两者选一个。AFTER|FOR:指定触发器指定的操作成功执行后被触发,两者选一个,实现的功能相同。操作:指定触发器触发的操作,DDL触发器触发的事件。SQL语句:触发器实现的操作。CREATE TRIGGER triddlON DATABASEFOR ALTER_TABLEASBEGINPRINT '不能修改表'ROLLBACKENDALTER TABLE 学生 ADD 健康状况 varchar(6)【例8-29】在学生管理数据库中,创建触发器triddl,不允许对数据库中的表作任何修改。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如图所示,测试触发器的功能。DDL触发器创建完成后,如果需要修改定义,则把CREATE改为ALTER即可。修改DDL触发器ALTER TRIGGER triddlON DATABASEFOR DROP_TABLEASBEGINPRINT '不能删除表'ROLLBACKEND--触发器触发的事件DROP TABLE 学生备份【例8-30】在学生管理数据库中,修改触发器triddl,不允许对数据库中的表进行删除操作。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如图所示,测试触发器的功能。使用DROP TRIGGER命令删除DDL触发器的语法规则如下:删除DDL触发器DROP TRIGGER 触发器名ON ALLSERVER|DATABASE参数说明如下:触发器名:指定要删除的触发器的名称,如果是多个触发器,名称之间用逗号分隔。ALLSERVER|DATABASE:指定删除的触发器的作用域。DROP TRIGGER triddl ON DATABASE--触发器触发的事件DROP TABLE 学生备份【例8-31】在学生管理数据库中,删除触发器triddl。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】按钮,由于限制删除表的触发器已经不存在了,则会删除成功。创建DML触发器修改DML触发器删除DML触发器查看DML触发器禁用和启用DML触发器DML触发器的创建与管理使用CREATE TRIGGER命令创建DML触发器的语法规则如下:创建DML触发器CREATE TRIGGER 触发器名ON 表名|视图名AFTER|FOR|INSTEAD OF [INSERT][,][UPDATE][,][DELETE]ASBEGINSQL语句END参数说明如下:触发器名:指定定义的触发器名称,遵守标识符的命名规则,但不能以#或##开头,建议前缀加tri。表名|视图名:指定触发器所在的表名或视图名,两者选一个,视图只能被INSTEAD OF触发器引用。AFTER|FOR|INSTEAD OF:AFTER或FOR指定DML触发器仅在触发SQL语句中指定的所有操作都已成功执行时才触发,INSTEAD OF替代类型触发器,执行触发器的操作来替代触发的SQL语句的执行。对于每一个INSERT、UPDATE或DELETE语句只能定义一个INSTEAD OF触发器。[INSERT][,][UPDATE][,][DELETE]:激活触发器的操作,这里可以选取任意组合,中间用逗号隔开。SQL语句:触发器实现的操作。CREATE TRIGGER triinsertstuON 系部AFTER INSERTASPRINT '数据插入成功!'INSERT INTO 系部 VALUES(6,'会计系','61232123','潘刚')【例8-32】在“系部”表中,创建插入语触发器triinsertstu,一旦数据插入成功,打印一个提示消息“数据插入成功”。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如图所示,在表中执行插入操作,触发器被激活,提示“数据插入成功!”。③在“查询编辑器”输入“SELECT * FROM 系部 WHERE 系部代码=6”,单击工具栏上的【执行】,可以查看到刚增加的记录。CREATE TRIGGER trimajorON 专业 FOR UPDATEASBEGINIF UPDATE(专业代码)BEGINPRINT '专业代码是主键,不允许更新!'ROLLBACKENDENDUPDATE 专业 SET 专业代码=9WHERE 专业名称='信息管理技术'【例8-33】在“专业”表中,创建一个触发器trimajor,禁止更新专业代码字段。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如图所示,在表中执行更新专业代码字段,触发器被激活,提示“专业代码是主键,不允许更新!”。③在“查询编辑器”输入“SELECT * FROM 专业 WHERE 专业名称='信息管理技术'”,单击工具栏上的【执行】,可以查看专业代码还是原来的4。CREATE TRIGGER tricourseON 课程 INSTEAD OF DELETEASBEGINIF EXISTS(SELECT * FROM deleted WHERE 课程性质 LIKE '%必修%')BEGINPRINT '不能删除必修课程,包括专业必修课和公共必修课'ROLLBACKENDENDDELETE 课程 WHERE 课程性质='专业必修课'【例8-34】在课程表中,创建一个触发器tricourse,禁止删除必修课程。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,触发器创建成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如图所示,在表中删除专业必修课,触发器被激活,提示“不能删除必修课程,包括专业必修课和公共必修课!”。DML触发器创建完成后,如果需要修改定义,则把CREATE改为ALTER即可。修改DML触发器【例8-35】在课程表中,修改触发器tricourse,提示用户正在修改必修课程,并取消操作。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:ALTER TRIGGER tricourseON 课程 INSTEAD OF UPDATEASBEGINIF EXISTS(SELECT * FROM INSERTED WHERE 课程性质 LIKE '%必修%')BEGINPRINT '您正在修改被保护的必修课程,请取消您的操作'ROLLBACKENDEND②单击工具栏上的【执行】按钮,触发器修改成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,如上图所示,测试触发器的功能。UPDATE 课程 SET 学分=6 WHERE 课程性质='专业必修课'使用DROP TRIGGER命令删除DML触发器的语法规则如下:删除DML触发器DROP TRIGGER 触发器名【例8-36】在学生管理数据库中,删除触发器triddl。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:DROP TRIGGER triinsertstu②单击工具栏上的【执行】按钮,触发器删除成功后,再在“查询编辑器”输入触发器触发的操作,单击工具栏上的【执行】,由于INSERT触发器已经不存在了,则不会提示插入成功。INSERT INTO 系部 VALUES(7,'物理系','62109876','王青')可以使用系统存储过程sp_help和sp_helptext查看触发器的相关信息。查看DML触发器sp_help tricourse【例8-37】分别用sp_help和sp_helptext查看触发器tricourse的信息。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,执行结果如图8-39所示。②单击工具栏上的【执行】按钮,执行结果如图所示。sp_helptext tricourse③在“查询编辑器”输入以下代码,单击工具栏上的【执行】,执行结果如图所示。当不需要一个触发器的时候,可以删除触发器,如果以后还需要该触发器,那么就要重新创建触发器,除了删除触发器,还可以禁用触发器,当触发器被禁用,该触发器还存在于当前数据库中,但是触发器不会被触发,如果以后再次需要该触发器,还可以重新启用触发器。禁用和启用DML触发器DISABLE TRIGGER 触发器名 ON 表名ENABLE TRIGGER 触发器名 ON 表名使用DISABLE TRIGGER语句禁用触发器的语法如下:使用ENABLE TRIGGER语句启用触发器的语法如下:DISABLE TRIGGER tricourse ON 课程【例8-38】禁用课程表的触发器tricourse。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,禁用触发器后,在“查询编辑器”输入语句“INSERT INTO 课程 VALUES(6,'MYSQL数据库','专业必修课',3,'第二学期','专业拓展')”,在课程表中先添加一条记录(因为课程表的信息在选课表中有外键引用,则不允许删除)。③在“查询编辑器”输入语句“DELETE FROM 课程 WHERE 课程编号=6”,单击工具栏上的【执行】,则触发器不能被激活,会成功删除必修课程。ENABLE TRIGGER tricourse ON 课程【例8-39】启用课程表的触发器tricourse。①打开SQL Server Management Studio,在工具栏上单击“新建查询”按钮,打开SQL编辑器,编写如下代码:②单击工具栏上的【执行】按钮,禁用触发器后,在“查询编辑器”输入语句“INSERT INTO 课程 VALUES(7,'ACCESS数据库','专业必修课',3,'第一学期','专业拓展')”,在课程表中先添加一条记录(因为课程表的信息在选课表中有外键引用,则不允许删除)。③在“查询编辑器”输入语句“DELETE FROM 课程 WHERE 课程编号=7”,单击工具栏上的【执行】,触发器被激活,提示“您正在修改被保护的必修课程,请取消您的操作”。在销售数据库中,在“商品类型”表中创建一个触发器,如果有此类型的商品信息,则不允许删除商品类型的信息。1.打开SQL Server Management Studio,单击“对象资源管理器”中的“数据库”文件夹下的数据库“销售”;2.单击工具栏上的“新建查询”命令,打开“查询编辑器”;3.在“查询编辑器”上输入以下代码:8.3.5 应用实践CREATE TRIGGER triproducttypeON 商品类型 INSTEAD OF DELETEASBEGINIF EXISTS(SELECT * FROM 商品 WHERE 类别ID IN(SELECT 类别ID FROM deleted ))BEGINPRINT '不能删除该商品类别,在商品表中有此类别的商品信息'ROLLBACKENDENDDELETE FROM 商品类型 WHERE 类别ID=24.单击工具栏上的【执行】按钮,如图所示。5.在“查询编辑器”上输入以下语句之后,单击工具栏上的【执行】按钮,运行结果如图所示。1.常量与变量。2.选择结构IF...ELSE语句。3.多分支选择结构CASE...WHEN...THEN语句。4.循环结构WHILE语句。5.RETURN语句。6.创建函数CREATE FUNCTION语句。7.修改函数ALTER FUNCTION语句。8.删除函数DROP FUNCTION语句。9.创建存储过程CREATE PROCEDURE语句。10.修改存储过程ALTER PROCEDURE语句。11.删除存储过程DROP PROCEDURE语句。12.创建触发器CREATE TRIGGER语句。13.修改触发器ALTER TRIGGER语句。14.删除触发器DROP TRIGGER语句。15.触发器的启用ENABLE TRIGGER语句和触发器的禁用DISABLE TRIGGER语句。本章小结 展开更多...... 收起↑ 资源预览