存储过程

从基本认知到深入理解

一、先理论上认识下

 

1.定义

存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

存储过程是由流控制和SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。存储过程是利用SQL Server所提供的Transact-SQL语言所编写的程序。Transact-SQL语言是SQL Server提供专为设计数据库应用程序的语言,它是应用程序和SQL Server数据库间的主要程序式设计界面。

以下功能,让用户可以设计出符合引用需求的程序:

  1)、变量说明

  2)、ANSI兼容的SQL命令(如Select,Update….)

  3)、一般流程控制命令(if…else…、while….)

  4)、内部函数

2.为什么要用存储过程

相对于直接使用SQL 语句,在应用程序中直接调用存储过程有以下好处:

     1)、减少网络通信量。

调用一个行数不多的存储过程与直接调用SQL 语句的网络通信量可能不会有很大的差别,可是如果存储过程包含上百行SQL 语句,那么其性能绝对比一条一条的调用SQL 语句要高得多。

     2)、执行速度更快。

有两个原因:首先,在存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用。

     3)、更强的适应性.

由于存储过程对数据库的访问是通过存储过程来进行的,因此数据库开发人员可以在不改动存储过程接口的情况下对数据库进行任何改动,而这些改动不会对应用程序造成影响。
     4) 、分布式工作.
应用程序和数据库的编码工作可以分别独立进行,而不会相互压制。

(ps:有些也并没有亲身感受到,而且一些定义好抽象)

3.存储过程的种类

      1)、系统存储过程:以sp_开头,用来进行系统的各项设定.取得信息.相关管理工作,

  如 sp_help就是取得指定对象的相关信息

  2)、扩展存储过程以XP_开头,用来调用操作系统提供的功能

  exec master..xp_cmdshell 'ping 10.8.16.1'

  3)、用户自定义的存储过程,这是我们所指的存储过程

 二、书写的格式

语法
CREATE PROC[ EDURE ] [ owner. ] procedure_name [ ; number ]
    [ { @parameter data_type }
        [ VARYING ] [ = default ] [ OUTPUT ]
    ] [ ,...n ]

[ WITH
    { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]

[ FOR REPLICATION ]

AS sql_statement [ ...n ]
解释

owner

    拥有存储过程的用户 ID 的名称。owner 必须是当前用户的名称或当前用户所属的角色的名称。

procedure_name

    新存储过程的名称。过程名必须符合标识符规则,且对于数据库及其所有者必须唯一。

;number

    是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为
orderpr;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。


 

@parameter

    过程中的参数。在 CREATE PROCEDURE 语句中可以声明一个或多个参数。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值,或者该值设置为等于另一个参数)。存储过程最多可以有 2.100 个参数。

使用 @ 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。

data_type

    参数的数据类型。除 table 之外的其他所有数据类型均可以用作存储过程的参数。但是,cursor 数据类型只能用于 OUTPUT 参数。如果指定 cursor 数据类型,则还必须指定 VARYING 和 OUTPUT 关键字。对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。

VARYING

    指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。

default

    参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。

OUTPUT

    表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。

n

    表示最多可以指定 2.100 个参数的占位符。

{RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}

    RECOMPILE 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。

ENCRYPTION 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。

FOR REPLICATION

    指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。

AS

   指定过程要执行的操作。

sql_statement

   过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。

n

   是表示此过程可以包含多条 Transact-SQL 语句的占位符。

一个最简单的存储过程:

CREATE PROCEDURE [dbo].[SP_GetAdminRecord]
AS select * from f_admin

--dbo:数据库的拥有者,对数据库拥有所有的权限操作

--SP_GetAdminRecord:存储过程名称
实例:
(1)不带参数
IF OBJECT_ID ( 'SP_GetAdminRecord', 'P' ) IS NOT NULL
    DROP PROCEDURE SP_GetAdminRecord;
GO
CREATE PROCEDURE [dbo].[SP_GetAdminRecord]
select adminname,tel from f_admin
GO

执行
execute SP_GetAdminRecord
--OR exec SP_GetAdminRecord

(2)带参数
IF OBJECT_ID ( 'SP_GetAdminRecord', 'P' ) IS NOT NULL
    DROP PROCEDURE SP_GetAdminRecord;
GO
CREATE PROCEDURE [dbo].[SP_GetAdminRecord]
@adminname nvarchar(20),
@tel nvarchar(50)

AS
select adminname,tel from f_admin
where adminname=@adminname AND tel=@tel

GO
 

执行:

execute SP_GetAdminRecord N'admin',N'123123477777777';

 


三、调用

界面:加了一个lable,id为lable1

    SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=***t;User ID=***;Password=l*****");
        SqlCommand cmd = new SqlCommand("SP_GetAdminRecord", con);
     
        cmd.CommandType = CommandType.StoredProcedure;
        con.Open();
        try
        {
            SqlDataReader dr = cmd.ExecuteReader();
          if (dr.Read())
            {
                lable1.Text = "oK!";
            
            }
         
      
            else
            {
              lable1.Text = "no oK!";

            } con.Close();
        }
           
        catch (Exception ex)
        {
            con.Close();
            lable1.Text = "异常";
        }

 

posted @ 2010-05-04 10:23  liuwei0214  阅读(214)  评论(0编辑  收藏  举报