数据库学习-视图、触发器、存储过程

数据视图

  • 复用性:数据库中关于数据的查询有时候非常复杂,例如表连接,子查询等,这种查询会让程序员感到非常痛苦,因为它逻辑复杂,编写语句较多,这种查询需要重复使用时,则不会次次都能编写成功,从而降低了数据库的实用性。
  • 安全性:在操作表时,有时候只要求程序员只能操作部分字段,而不是全部字段。比如在公司,工资一般是保密的,如果因为程序员一时疏忽多写入一个”工资“字段,则会让员工的工资显示给所有人,这就需要限制程序员操作的字段。

所以为了提高复杂SQL语句的复用性和安全性,则可以使用视图。

视图:本质上是一种虚拟表,其内容与真实的表相似,包含一系列带有名称的列和行数据,但是,视图并不在数据库中以存储的数据值形式存在。行和列数据来自定义视图的查询所引用基本表,并不在具体引用视图时动态生成。

视图使程序员只关心需要的数据和所负责的特定任务,这样程序员只能看到视图中定义的数据,而不是视图所引用表中的数据,从而提高数据库中数据的安全性。

视图特点

  • 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系
  • 视图是由基本表(实表)产生的虚表
  • 视图的建立和删除不影响基本表
  • 对视图内容的更新(添加删除修改)直接影响基本表
  • 当视图来自多个基本表时,不允许添加和删除数据

创建视图语法

create view view_name as 查询语句

和创建表一样,视图名不能重复,从语法可发现,视图的功能其实就是封装了复杂的查询语句。

查询视图

select * from view_name

MySQL视图

SQL Server视图

触发器

SQL触发器是存储在数据库目录中的一组SQL语句。每当与表相关联的事件发生时,即会执行或触发SQL触发器,例如插入,更新或删除。

SQL触发器是一种特殊类型的存储过程。与一般存储过程不同的是,触发器不是被调用执行,而是当对表执行数据修改事件时,会自动调用触发器,而存储过程必须要明确地调用。触发器不能传递参数和接受参数。它与数据表关系密切,一般用于实现比较复杂的数据完整性规则、检查数据的有效性、实现对用户操作和数据状态的实时监控、实现数据库的一些管理任务和其他的一些附加功能等。

SQL触发器的优点

SQL触发器提供了检查数据完整性的替代方法。SQL触发器可以捕获数据库层中业务逻辑中的错误。SQL触发器提供了运行计划任务的另一种方法。通过使用SQL触发器,您不必等待运行计划的任务,因为在对表中的数据进行更改之前或之后自动调用触发器。SQL触发器对于审核表中数据的更改非常有用。

SQL触发器的缺点

SQL触发器只能提供扩展验证,并且无法替换所有验证。一些简单的验证必须在应用层完成。 例如,您可以使JavaScript或服务器端使用服务器端脚本语言(如JSP,PHP,ASP.NET,Perl等)来验证客户端的用户输入。从客户端应用程序调用和执行SQL触发器不可见,因此很难弄清数据库层中发生的情况。SQL触发器可能会增加数据库服务器的开销。

DML触发器

数据库操纵语言(DML)主要包含INSERT、UPDATE、DELETE等语句。这些语句作用于数据表或视图的时候,将产生相应的事件——DML事件。此类事件一旦发生可引起相关触发器的执行,因此这类事件通常称为DML事件,相应的触发器称为DML触发器。也可以这样理解,DML触发器是在运行DML语句时由于产生DML事件而被执行的一类触发器。

根据触发器的执行与触发事件发生的先后关系,又可以将DML触发器分为AFTER触发器和INSTEAD OF触发器。

AFTER触发器:

在DML触发事件发生后才激发执行的触发器,也就是说,先执行INSERT、UPDATE、DELETE语句然后才执行AFTER触发器。这类触发器只适用于数据表,不适用于视图。AFTER触发器一般用于检查数据的变动情况,以便采取相应的措施。例如,如发现错误,将拒绝或回滚更改的数据;

INSTEAD OF触发器:“

INSTEAD OF”的中文意思就是“代替”之意,由此不难理解:INSTEAD OF触发器是在DML触发事件发生之前(即数据被更新之前)执行的,这种执行将代替DML语句的执行。也就是说,INSTEAD OF触发器是在DML触发事件发生之前执行,并且取代相应的DML语句(INSERT、UPDATE或DELETE语句),转而去执行INSTEAD OF触发器定义的操作(此后不再执行此DML语句)。INSTEAD OF触发器既适用于数据表,也适用于视图。但对同一个操作只能定义一个INSTEAD OF触发器。

如果根据触发事件的类型划分,DML触发器通常又可以分为INSERT触发器、UPDATE触发器和DELETE触发器:

INSERT触发器:执行INSERT语句而激发执行的触发器;

UPDATE触发器:执行UPDATE语句而激发执行的触发器;

DELETE触发器:执行DELETE语句而激发执行的触发器。

DDL触发器

DDL触发器是一种由执行DDL语句产生触发事件而触发执行的触发器。DDL语句包括CREATE、ALTER、DROP、GRANT、DENY、REVOKE 和UPDATE STATISTICS 等语句。

Ø 与DML触发器不同的是,DDL触发器的触发事件是执行DDL语句而引起的事件,这种触发器是在触发事件发生后执行的;而DML触发器的触发事件则是由执行DML语句引起的,可在事件发生前或发生后执行。另外,DDL触发器的作用域不是架构,因而不能使用OBJECT_ID来查询有关DDL触发器的元数据。DDL触发器可用于执行数据库级的管理任务,如审核和规范数据库操作等。

DML触发器的触发事件类型比较简单,主要包括INSERT、DELETE和UPDATE等三种事件。但DDL触发器的触发事件就比较多,表9.1列了出常用的几种事件。记住这几种事件对以后的触发器编程很有帮助。

LOGON触发器(登录触发器)

登录触发器是SQL Server 2005开始新增加的一类为响应LOGON事件(登录)而激发执行的触发器。也就是说,只要有用户登录,登录触发器即可激发执行。因此,通过登录触发器可以知道谁登录了服务器以及何时登录的,并可以实现如何跟踪用户的活动,还可以限制特定用户只能在特定时间段登录等。

触发事件对触发器来说是关键的,所以许多时候又用引发触发事件的SQL语句来对触发器进行分类和命名。

INSERT触发器、DELETE触发器、UPDATE触发器等。但这种分类不是严格的,只是为阐明问题之便。

创建DML触发器

CREATE TRIGGER [ schema_name. ]trigger_name
ON { table | view }
[ WITH <dml_trigger_option> [ ,...n ] ]
{ FOR | AFTER | INSTEAD OF }
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS { sql_statement  [ ; ] [ ...n ] | EXTERNAL NAME <method specifier [ ; ] > }
<dml_trigger_option> ::= [ ENCRYPTION ] [ EXECUTE AS Clause ]
<method_specifier> ::= assembly_name.class_name.method_name

参数说明如下:

  • trigger_name:设置触发器的名称,但不能以#或##开头。

  • schema_name:设置触发器所属架构的名称。

  • table | view:执行DML触发器的表或视图,也分别称为触发器表或触发器视图。

  • WITH ENCRYPTION:选择该子句,则表示对触发器文本进行加密。

  • EXECUTE AS:指定用于执行该触发器的安全上下文,即设置操作权限。

  • AFTER:表示定义AFTER触发器,即DML触发器在触发事件发生后执行。如果仅指定FOR关键字,则默认使用AFTER。

  • INSTEAD OF:表示定义INSTEAD OF触发器,即DML触发器在触发事件发生之前执行。

  • { [DELETE] [,] [INSERT] [,] [UPDATE] }:指定触发事件,如果选择了DELETE,则表示创建DELETE触发器,其他类推。

  • WITH APPEND:指定添加一个与当前触发器类型相同的另外一个触发器。该子句不适用于INSTEAD OF触发器。该功能在未来中将被删除,建议不要使用。

  • NOT FOR REPLICATION:该选项用于指示复制代理修改到触发器表时不执行触发器。

  • sql_statement:SQL语句。

  • < method_specifier >:只适用于CLR触发器,指定程序集与触发器绑定的方法。

如果在CREATE TRIGGER语句中选择了INSERT 、UPDATE或DELETE选项,则表示创建INSERT,UPDATE或DELETE触发器。对于这类触发器(DML触发器),有两种临时表与它们有着密切的联系,它们是表DELETED和表INSERTED。这两种临时表都是在触发器执行时被创建,执行完毕后被删除。对它们的维护和管理是由SQL Server自动完成,用户不能对这两个表进行直接操作。

具体地,在执行INSERT触发器时创建表INSERTED,执行DELETE触发器时创建表DELETED,执行UPDATE触发器时则同时创建表INSERTED和表DELETED,其中表INSERTED保存了更新的数据记录,表DELETED则保存更新前的数据记录(不受到更新影响的记录不含在其中)。

SQL Server对这两个表的操作过程如下:
INSERTED:在执行INSERT或UPDATE语句时,对用于插入或用于更新的数据记录拷贝一个副本,并将该副本保存到表INSERTED中。可见,表INSERTED是触发器表被插入或被更新后的一个子集。
DELETED:在执行DELETE和UPDATE语句时,将触发器表中被删除或被更新的数据记录拷贝到表DELETED中。可见表DELETED和触发器表是不相交的(不会含有相同的记录)。

假设表param是参数表,有code和name两个字段,在保存修改是不允许code重复。

USE dbo
GO
CREATE TRIGGER checkcode_trigger ON param
AFTER INSERT,UPDATE
AS
BEGIN
  DECLARE @code char(8), @n int;
  SELECT @code = p.code             -- 将正在插入的记录的code字段值保存在@code中
  FROM param AS p 
SELECT @n = COUNT(*)                 -- 在表param中查找是否有code字段值等于@code的学生
  FROM param
  WHERE code = @code;  
IF @n > 1
  BEGIN
     RAISERROR ('code不能重复', 16, 1);
     ROLLBACK TRANSACTION;   -- 回滚(撤销前面的插入修改操作)
   END
   ELSE PRINT '执行成功';
END
GO

出于某种原因(如学生因退学、出国而取消学籍),有时候需要将表student中的记录删除,这时也应该将表SC中对应学生的选课信息删除,以保持数据库的完整性。这种完整性的保持可以通过定义如下的AFTER触发器来实现。

USE MyDatabase
GO
CREATE TRIGGER myTrigger3 ON student
AFTER DELETE
AS
BEGIN
  DECLARE @s_no char(8);
  SELECT @s_no = I.s_no        
  FROM DELETED AS I;
  DELETE FROM SC
  WHERE s_no = @s_no;
END
GO

该触发器的作用就是,当在表student中删除某一条件记录时,表SC中与该记录对应的记录(字段s_no值相同的记录)将自动被删除,以保持两个表中数据的参照完整性。

修改触发器

触发器的修改是由ALTER TRIGGER语句来完成。但修改不同类型的触发器,ALTER TRIGGER语句的语法是不相同的。

以下分别是修改DML触发器和DDL触发器的SQL语句:

ALTER TRIGGER schema_name.trigger_name      -- 修改DML触发器
ON ( table | view )
[ WITH <dml_trigger_option> [ ,...n ] ]
( FOR | AFTER | INSTEAD OF )
{ [ DELETE ] [ , ] [ INSERT ] [ , ] [ UPDATE ] }
[ NOT FOR REPLICATION ]
AS { sql_statement [ ; ] [ ...n ] | EXTERNAL NAME <method specifier> [ ; ] }
<dml_trigger_option> ::= [ ENCRYPTION ] [ <EXECUTE AS Clause> ]
<method_specifier> ::= assembly_name.class_name.method_name

ALTER TRIGGER trigger_name        -- 修改DDL触发器
ON { DATABASE | ALL SERVER }
[ WITH <ddl_trigger_option> [ ,...n ] ]
{ FOR | AFTER } { event_type [ ,...n ] | event_group }
AS { sql_statement [ ; ] | EXTERNAL NAME <method specifier> [ ; ] }
}
<ddl_trigger_option> ::= [ ENCRYPTION ] [ <EXECUTE AS Clause> ]
<method_specifier> ::= assembly_name.class_name.method_name

其中涉及的参数与触发器定义语法中的参数一样。注意,不能为DDL触发器指定架构schema_name。

修改触发器的优点:主要是用户拥有对它的操作权限不会因为对触发器的修改而发生改变。另外,如果原来的触发器定义时使用WITH ENCRYPTION或WITH RECOMPILE选项创建的,只有在ALTER TRIGGER中也包含这些选项时,这些选项才有效。

禁用和删除触发器

有时候(特别是在调试阶段)我们并不希望频繁地触发执行一些触发器,但又不能将之删除,这时最好先禁用这些触发器。

禁用一段时间以后,一般还需重新启用它,这又要涉及到触发器启用的概念。

以下分别是禁用和启用触发器的SQL语法:

DISABLE TRIGGER { [ schema. ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]
ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]

参数说明如下:

  • trigger_name:要禁用的触发器的名称。

  • schema_name:触发器所属架构的名称。但DDL触发器没有架构。

  • ALL:如果选择该选项,则表示对定义在ON子句作用域中的所有触发器全部禁用。

  • object_name:触发器表或视图的名称。

  • DATABASE:将作用域设置为整个数据库。

  • ALL SERVER:将作用域设置为整个服务器。

删除触发器

当确信一个触发器不再使用时,应当将之删除。DML触发器和DDL触发器的删除方法有所不同,以下分别是删除这两种触发器的SQL语法:

DROP TRIGGER schema_name.trigger_name [ ,...n ] [ ; ]  -- 删除DML触发器
DROP TRIGGER trigger_name [ ,...n ] ON { DATABASE | ALL SERVER } [ ; ] -- 删除DDL触发器

在删除DDL触发器时需要指定触发器名称和作用域(即,是DATABASE还是ALL SERVER),而删除DML触发器时则只需指定其名称。

存储过程

存储过程是指封装了可重用代码的、存储在服务器上的程序模块或例程。存储过程是数据库对象之一,它类似于其他高级编程语言中的过程或子程序,编译成可执行代码后保存在服务器上,可多次调用。

其特点体现在:

  • 可以接受多个输入参数,能够以多输出参数的格式返回多个值。

  • 在服务器端运行,使用EXECUTE(简写为EXEC)语句来执行。

  • 可以调用其他存储过程,也可以被其他语句或存储过程调用,但不能直接在表达式中使用。

  • 具有返回状态值,表明被调用是成功还是失败。但不返回取代其名称的值,这是它与函数的不同之处。

  • 存储过程已在服务器注册。

存储过程的优点主要体现在:

  • 提高程序的执行效率。存储过程执行在第一次被执行以后,其执行规划就驻留在高速缓冲存储器中。在以后的每次操作中,只需从高速缓冲存储器中调用已编译好的二进制代码执行即可,而不必重新编译再执行,从而提高了执行效率。

  • 具有较高的安全特性。作为一种数据库对象,存储过程要求拥有相应权限的用户才能执行它。同时,它也提供了一种更为灵活的安全性管理机制:用户可以被授予权限来执行存储过程,而不必对存储过程中引用的对象拥有访问权限。

  • 如果一个存储过程是用于更新某一个数据表的,那么只要用户拥有执行该存储过程的权限,他就可以通过执行该存储过程的方法来实现对指定数据表的更新操作,而不必直接拥有对该数据表操作的权限。

  • 减少网络通信流量。由于存储过程在服务器端执行,用户每次只需发出一条执行命令,而不必发出存储过程所有的冗长代码,因而减少了网络的数据流量。

  • 允许模块化程序设计,提高代码的可重用性。存储过程一旦被创建,以后就可以在所有程序中多次调用。这有利于程序的结构化设计,提高程序的可维护性和代码的可重用性。

存储过程的类型

  • 在SQL Server 2008中,存储过程可以分为两种类型:SQL存储过程和CLR存储过程。SQL存储过程是指出由SQL语言编写而形成的存储过程,它是SQL语句的集合。CLR(Common Language Runtime)存储过程是指引用Microsoft.NET Framework公共语言运行时(CLR)方法的存储过程,它在.NET Framework程序集中是作为类的公共静态方法实现的。

  • 根据来源和应用目的的不同,又可以将存储过程分为用户存储过程、系统存储过程和扩展存储过程。

系统存储过程

系统存储过程是SQL Server 2008本身定义的、当作命令来执行的一类存储过程。它主要用于管理SQL Server 数据库和显示有关数据库及用户的信息,通常前缀“sp_”。

sp_addrolemember就是一个用于为数据库角色添加成员的系统存储过程。从逻辑结构看,系统存储过程出现在每个系统定义数据库和用户定义数据库的sys构架中。读者最好能够熟悉一些常用的系统存储过程,以免重复开发。

用户存储过程

用户存储过程是指由用户通过利用SQL语言编写的、具有特定功能的一类存储过程。由于系统存储过程以“sp_”为前缀,扩展存储过程以“xp_”,所以用户存储过程在定义时最好不要使用“sp_”或“xp_”为前缀。如果需要,用户存储过程应以“up_”为前缀,“u”是单词user的头字母。

扩展存储过程

扩展存储过程是指SQL Server的实例可以动态加载和运行的动态链接库(DLL)。通过扩展存储过程,可以使用其他编程语言(如C语句)创建自己的外部程序,实现了SQL程序与其他语言程序的连接与融合。

扩展存储过程直接在SQL Server的实例地址空间中运行,可以使用SQL Server扩展存储过程API完成编程。但由于后续的SQL Server版本中将不支持扩展存储过程,所以在新的工程开发项目中应尽量少用或不用这种功能。

存储过程的创建和调用

存储过程是由CREATE PROCEDURE语句来创建,其语法如下:

CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ]
  [ { @parameter [ type_schema_name. ] data_type }
      [ VARYING ] [ = default ] [ [ OUT [ PUT ] ] [ ,...n ]
[ WITH <procedure_option> [ ,...n ]
[ FOR REPLICATION ]
AS { <sql_statement> [;][ ...n ] | <method_specifier> }[;]

<procedure_option> ::=
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE_AS_Clause ]

<sql_statement> ::= { [ BEGIN ] statements [ END ] }

<method_specifier> ::= EXTERNAL NAME assembly_name.class_name.method_name

对涉及的参数说明如下:

  • schema_name:设定存储过程所属架构的名称。

  • procedure_name:存储过程的名称。它是一个合法的标识符,在架构中是唯一的。存储过程名一般不能使用前缀“sp_”,此前缀由系统存储过程使用。如果过程名以井号“#”开头,则表示创建的过程将局部临时过程,这种过程名的长度不超116个字符(含#);如果以双井号“##”开头,则表示是全局临时过程,这种过程名的长度不超128个字符(含##)。

  • number:用于对同名的存储过程进行分组的整数。例如,myPro;1、myPro;2等。

  • @parameter:存储过程带的参数,data_type为参数所属架构的数据类型。参数可以是一个或者多个,最多为2,100个参数。在定义时参数可以设置默认值,而对于没有设置默认值的参数,在调用时必须为其提供值。在默认情况下,参数只能代表常量表达式,而不能用于代表表名、列名或其他数据库对象的名称。如果指定了FOR REPLICATION,则无法声明参数。

  • OUTPUT(或OUT):如果指定了OUTPUT(或OUT),则表示该参数为输出参数。输出参数用于将存储过程处理后的某些结果返回给调用它的语句。游标(cursor)数据类型参数必须指定OUTPUT,同时还必须指定关键字VARYING。一般情况下,text、ntext和image类型参数不能用作OUTPUT 参数。

  • VARYING:指定输出参数支持的结果集。仅适用于游标类型参数。

  • default:设定参数的默认值。如果定义了default值,则在调用存储过程时无需为此参数指定值,否则必须指定参数值才能调用。默认值必须是常量或NULL。

  • RECOMPILE:该选项用于指示SQL Server不要将存储过程的执行规划保存在高速缓冲存储器中,因为该过程在执行时要重新编译,然后才运行。如果指定了FOR REPLICATION,则不能使用此选项。

  • ENCRYPTION:指示SQL Server对CREATE PROCEDURE语句的原始文本进行加密,加密后的代码的输出在SQL Server 2008的任何目录视图中都不能直接显示。

  • EXECUTE AS:该子句用于指定在其中执行存储过程的安全上下文。

  • FOR REPLICATION:如果选择该选项,则表示创建的存储过程只能在复制过程中执行。该类过程不能声明参数,忽略RECOMPILE选项。

  • :表示包含在过程中的一个或多个SQL语句。

  • :CLR存储过程的标识。assembly_name.class_name.method_name用于指定.NET Framework程序集的方法,以便CLR存储过程引用。

(简单的存储过程)创建一个存储过程,它可以输出学生的学号、姓名、平均成绩以及所在系别。

该过程名为“myPro1”,所使用的SQL语句如下:

USE MyDatabase;     -- 设置当前数据库

GO

IF OBJECT_ID('myPro1','P') IS NOT NULL -- 判断是否已存在名为“myPro1”存储过程

    DROP PROCEDURE myPro1;    -- 如果存在则删除,否则无法创建(不是必备代码)

GO

CREATE PROCEDURE myPro1   -- 定义存储过程myPro1

AS

    SELECT s_no, s_name, s_avgrade, s_dept

    FROM student;

GO 

在SQL Server Management Studio中编写上述代码,然后运行此代码即可在服务器端生成存储过程myPro1,此后就可以调用此存储过程。

调用一个存储过程,一般是用EXECUTE(或EXEC)语句来完成。但也可以直接将过程名当作一个条命令来执行。

【例子】对于上面定义的过程myPro1,以下三种执行方式都是有效且等价的:

myPro1;             -- 这种没有EXECUTE或EXEC的执行方式必须位于批处理中的第一条语句

EXEC myPro1;        -- 这种格式通常用于嵌入到其他语言中

EXECUTE myPro1;     -- 这种格式通常用于嵌入到其他语言中

(带参数的存储过程)对于例9.1,进一步要求能够按照成绩段来查询学生的相关信息。满足本例要求的存储过程需要带参数,用于界定成绩段。该存储过程定义的代码如下:

USE MyDatabase;

GO

CREATE PROCEDURE myPro2    -- 定义带两个参数的存储过程

    @mingrade numeric(3,1) = 60,     -- 参数@mingrade的默认值为60

    @maxgrade numeric(3,1)    -- 参数@maxgrade没有设置默认值

AS

    -- 查询平均成绩在@mingrade到@maxgrade之间的学生信息

    SELECT s_no, s_name, s_avgrade, s_dept 

    FROM student

    WHERE s_avgrade>= @mingrade AND s_avgrade <= @maxgrade; 

GO

上述存储过程带有两个参数,所以调用该过程时必须为之指定相应的参数值。对于有默认值的参数,如果不指定参数值,则使用默认值,但调用格式要正确。例如,对于存储过程myPro2,可通过执行下列语句来查询平均成绩在60到90分之间的学生信息(它们都是等价的):

EXEC myPro2 60, 90;

EXEC myPro2 @mingrade = 60, @maxgrade = 90;

EXEC myPro2 @maxgrade = 90, @mingrade = 60;

EXEC myPro2 @maxgrade = 90; -- 参数@mingrade使用默认值60

但如果试图使用下列方式来执行过程myPro2,则是错误的或与题意相背:

EXEC myPro2 90;       -- 错误的调用格式,少了一个参数

EXEC myPro2 90, 60;  -- 能成功调用,但与题意相背
 

(带通配符参数的存储过程)创建一个存储过程,使之能够按照姓名模糊查询并列出学生的学号、姓名和平均成绩;如果在调用时不带参数,则列出所有学生的相关信息。

该存储过程使用带通配符的方法来实现,其代码如下:

USE MyDatabase;

GO

CREATE PROCEDURE myPro3          

    @s_name varchar(8) = '%'

AS 

    SELECT s_no, s_name, s_avgrade, s_dept 

    FROM student

    WHERE s_name LIKE @s_name; 

GO

调用该过程时,如果带参数值则按姓名进行模糊查询,如果不带参数值则列出所有学生的相关信息。

【例子】下列语句将列出所有的姓“王”的学生信息:

EXEC myPro3 '王%';  

而执行下列语句后则列出所有学生的学号、姓名和平均成绩:

EXEC myPro3;

(带OUTPUT参数的存储过程)创建一个存储过程,使之能够求出所有学生成绩的总和以及女学生成绩的总和。

OUTPUT参数可以从存储过程中“带回”返回值,因此利用OUTPUT参数可以让存储过程具有返回值功能.本例中的存储过程要求有两个返回结果,因此在定义存储过程时需要声明带两个OUTPUT参数。

定义该过程的代码如下:

USE MyDatabase;

GO

CREATE PROCEDURE myPro4      

    @ s_total real OUTPUT,                                  --声明OUTPUT参数

    @ s_total _female real OUTPUT,           --声明OUTPUT参数

AS

    SELECT @ s_total =SUM(s_avgrade)                     --求所有学生成绩总和

    FROM student;

    SELECT @ s_total _female =SUM(s_avgrade)              --求女学生成绩总和

    FROM student

   WHERE s_sex=‘女’

GO

对于带OUTPUT参数的存储过程,其调用方法与其他的存储过程的调用方法有所不同。首先要声明相应的变量来存放返回结果,然后在调用过程的时候要带关键字OUTPUT,否则无法将返回结果保存下来。

【例子】要获取存储过程myPro4返回的结果并打印出来,相应的代码如下:

DECLARE @total real, @total_female real;

EXEC myPro4 @total OUTPUT, @total_female OUTPUT;  -- 调用时要带关键字OUTPUT

print @total;

print @total_female;

(加密存储过程)创建一个加密的存储过程。

加密存储过程是指在存储过程被创建后对保存在服务器端的过程文本代码进行加密,从而无法使用文本编辑器来查看代码。

加密存储过程的方法很简单,只要在定义时使用WITH ENCRYPTION子句即可。以下是一个加密存储过程的定义代码:

USE MyDatabase;        

GO

CREATE PRO CEDURE myPro5   WITH ENCRYPTION          

AS

    SELECT s_no, s_name, s_avgrade, s_dept

    FROM student;

GO

一个存储过程的定义文本可以用系统存储过程sp_helptext来查看。但执行下列语句后,会显示对象已加密的信息,这表示myPro5的定义文本已经被加密:

EXEC sp_helptext myPro5;

存储过程的修改和删除

修改存储过程

存储过程的修改可用ALTER PROCEDURE语句来实现,修改后用户对该存储过程拥有的权限并没有发生改变。

ALTER PROCEDURE语句的语法如下:

ALTER { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ]
    [ { @parameter [ type_schema_name. ] data_type }
    [ VARYING ] [ = default ] [ [ OUT [ PUT ] ] [ ,...n ]
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ]
AS
     { <sql_statement> [ ...n ] | <method_specifier> }
<procedure_option> ::=
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE_AS_Clause ]
<sql_statement> ::= { [ BEGIN ] statements [ END ] }
<method_specifier> ::= EXTERNAL NAME assembly_name.class_name.method_name

注意:如果原来的存储过程在定义时使用了WITH ENCRYPTION或WITH RECOMPILE选项,那么只有在ALTER PROCEDURE语句中也选择了这些选项,这些选项才有效;另外,使用ALTER PROCEDURE修改后,原过程的权限和属性将保持不变。

对创建的存储过程myPro3进行修改,使之能够按照姓名(s_name)或系别(s_dept)进行查询。

该修改操作可用下列的ALTER PROCEDURE来实现。

ALTER PROCEDURE myPro3                

    @s_name varchar(8) = '赵%',

    @s_dept varchar(50) = '%'

AS 

    SELECT s_no, s_name, s_avgrade, s_dept 

    FROM student

    WHERE s_name LIKE @s_name OR s_dept LIKE @s_dept;

GO
   修改后的过程与原来过程的权限完全一样。不同的是它除了可以按姓名查询外,还可以按系别查询。

在SSMS中修改存储过程的方法是,在对象资源管理中右击要修改的存储过程所对应的节点,并在弹出的菜单中选择“修改”命令,然后在打开的查询编辑器窗口中修改过程的定义代码即可。但对加密存储过程,则无法用这种方法修改。

删除存储过程

当一个存储过程不再使用时,就应该将它从数据库中删除。删除一个存储过程的SQL语句是DROP PROCEDURE。实际上,在前面介绍的例子中已经多次用到。其语法如下:

DROP { PROC | PROCEDURE } { [ schema_name. ] procedure } [ ,...n ]
 从该语法中可以看出,一条DROP PROCEDURE语句可以同时删除一个或多个存储过程。

同时删除过程myPro1, myPro2, myPro3,可使用下列语句来完成:

DROP PROCEDURE myPro1, myPro2, myPro3;

也可以在SSMS中删除一个存储过程。方法是:在对象资源管理器中右击要删除的存储过程所对应的节点,然后在弹出的菜单中选择“删除”命令,最后根据提示删除存储过程。

注意,当一个存储过程被删除以后,所有用户对其拥有的操作权限也将全部被删除。

你可能感兴趣的:(数据库,数据库,mysql,java,sqlserver)