canyue

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
n一、存储过程简介
n二、存储过程的创建、修改、删除
n三、存储过程中的参数、返回值和变量
n四、存储过程中的流程控制语言
n五、存储过程中的事务、游标
n六、ASE存储过程和IQ存储过程的常见区别(附例子)

 

1 存储过程简介
na.存储过程(Stored Procedure)是为了完成特定的功能而汇集成一组的SQL语句集,并为该组SQL语句命名、经编译后 存储在SQL Server的数据库中。用户可以根据需要决定是 否在每次执行时SQL Server进行重新编译。用户可以指 定存储过程的名字和给出参数来执行它。
nb.允许多个用户(有权)访问相同的代码。
nc.提供一种集中且一致的实现数据完整性逻辑的方法。
nd.存储过程用于实现:
n -- 频繁使用的查询
n -- 业务规则
n -- 被其他过程使用的公共例行程序,例如错误处理例行程序

 

1.1 存储过程的优点
n--使用存储过程可加快运行速度
n--可减少网络交通
n--可重用、可共享性
n--存储过程也是一种安全机制
n--使用存储过程实现数据库完整性
n--提高数据与应用的独立性
 
1.2 存储过程的分类
n--系统提供存储过程  系统存储过程主要用于从系统表中获取信息、为系统管理员和有权用户提供更新系统表的途径。系统存储 过程的名字都以"sp_"为前缀。 如:sp_help 。
n--用户定义存储过程  户定义的存储过程是由用户为完成某一特定功能 而编写的存储过程。

 

1.2.1 系统存储过程
在SQL Server安装时自动建立了一些以sp_为前缀的系统存储过程,这些系统过程通常用来显示或修改系统表它们可为各用户所供享:

 

2 存储过程的创建、修改、删除
n--创建存储过程
n--执行存储过程
n--查看、修改、删除存储过程
n--存储过程中的注释


2.1 创建存储过程
ncreate proc procedure_name
as
begin
     SQL_statements
     [return]
end

 
n--存储过程被放在当前正在使用的数据库中。
n--在存储过程中可以引用在其他数据库中的对象
n--创建存储过程(create proc)语句不能与其他的SQL语句在同一个批中,即创建存储过程语句必须单独成为一个批。
n--在存储过程中可以包含SQL语句,但是不能包含:use, create view, create rule, create default, create proc, create trigger

2.2 执行存储过程
n语法:
 [exec[ute]] procedure_name [参数]   

 

2.3 查看、修改和删除存储过程

 

n查看存储过程
--查看创建存储过程的源代码,使用: sp_helptext procedure_name
--查看存储过程所依赖的表和视图信息,使用: sp_depends procedure_name
--查看存储过程的一般信息,如创建日期等,使用: sp_help procedure_name
n重新命名存储过程
 语法sp_rename   old_name ,   new_name
 例:将已创建的存储过程reports_1改名为reports_1b:
 exec sp_rename reports_1, report_lb
n删除存储过程
 语法drop proc procedure_name
 例: 删除已创建的存储过程reports:
 drop proc reports

 

2.4 存储过程中的注释
nSQL Server提供了两种在T-SQL中的注释方法:
n 使用斜杠星号对/* 注示内容*/
例如:
/*bind the rule to all
columns with datatype*/
exec sp_bindrule ul_tid,tid

 

n— 使用双连字符“--”
例如:
--bind the rule to all columns
--with datatype tid
exec sp_bindrule ul_tid,tid
 
存储过程的参数、返回值和变量
n存储过程中的参数
n存储过程的返回状态
n存储过程中的变量

 

3.1 存储过程中的参数
输入参数(Input Parameters) 是指由调用程序向存储过程 提供的变量值。它们在创建存储过程语句中被定义,而 在执行该存储过程语句中给出相应的变量值。使用输入 参数的优点是使存储过程得更加灵活。
   
语法 create proc procedure_name
    (@parameter_name datatype
       [, @parameter_name datatype...])
       as
       begin
           SQL_statements
           return
       end

 

3.1.1 带参数存储过程
举例: 创建带参数的存储过程
create proc proc_author_addr (@lname varchar(40))
as
begin
select phone, address, city, state
from authors
where au_lname = @lname
return
-- 在调用程序的执行存储过程命令中,将相应的值传递给
-- 这个输入参数:用'Green'替换@lname
exec proc_author_addr @lname = 'Green'
   或
exec proc_author_addr 'Green‘
end
 
3.1.2 带有返回参数的存储过程
举例:
创建向调用程序返回值的存储过程:
create proc proc_num_sales
(@book_id char(6) = null, /* 输入参数 */
   @tot_sales int output /* 输出参数 */
as
begin
/* 过程将返回对于给定书号的书的总销售量 */
select @tot_sales = sum(qty) from salesdetail
   where title_id = @book_id
return
end

 

3.2 存储过程返回状态
 
na.每个存储过程的执行,都将自动返回一个返回状态,用于告知调用程序执行该存储过程的状况。调用程序可根据返回状态作相应的处理。
n语法:create proc procedure_name ( ...... )
     as
     begin
         SQL_statements
         return [ integer ]
     end
b.其中:integer为一整数。如果不指定,系统将自动返回一个整数值。系统使用0表示该过程执行成功;-1至–14 表示该过程执行有错,-15至 -99为系统保留值。用户一般使用大于0的整数,或小于 -100的负整数。
 
3.3 存储过程中的变量
n
n局部变量
n全局变量

3.3.1.1 局部变量的定义与声明

na.局部变量是
-用户自定义变量
-使用declare语句定义
-具有名和数据类型
-通过用户赋值
-说明时给变量赋值为空
-局部变量可在存储过程,或触发器中定义
nb.语法
DECLARE @var_name data_type
[, @var_name data_type]。。。
nc.举例
declare @msg    varchar(40)
declare @myqty int, @myid    char(4)
3.3.1.2 局部变量赋值
na.局部变量被声明时,它的初值为NULL ,使用SELECT语句将指定值赋给局部变量。
n语法
select @var = expression
[,@var = expression ]
[from
[where]
nb.举例
declare @var1 int
select @var1=99
nc.注意

在一个赋值给局部变量的select语句中,可以使用常数、从表中取值、或使用表达式给局部变量赋值。

不能使用同一SELECT语句既给局部变量赋值,又检索数据返回给客户。

一个赋值给局部变量的SELECT语句,不向用户显示任何值。

3.3.1.3 局部变量的限制
n局部变量必须先用DECLARE定义,再用SELECT语句赋值后才能使用。
n局部变量只能使用在TSQL语句中使用常量的地方。
n局部变量不能使用在表名、列名、其它数据库对象名、保留字使用的地方。
n局部变量是标量,它们拥有一个确切的值。
n赋值给局部变量的SELECT语句应该返回单个值。如果赋值的SELECT语句没有返回值,则该局部变量的值保持不变;如果赋值的SELECT语句返回多个值,则该局部变量取最后一个返回的值。
3.3.1.4 使用局部变量时通常发生的错误
n在程序中,使用局部变量通常容易发生的错误是数据类型不匹配。即使用DECLARE语句定义局部变量的数据类型与赋值给局部变量的值的数据类型不匹配。如果发生这种情况,SQL Server总是试图隐式转换为局部变量的数据类型。
3.3.2 全局变量

全局变量(Gloabal Variable )SQL Server系统提供并赋值的变量。用户不能建立全局变量,也不能使用SELECT语句去修改全局变量的值。全局变量的名字用@@开始。大多数全局变量的值报告本次SQL Server启动后发生的系统活动,可以使用系统存储过程sp_monitor显示全局变量的当前值。通常全局变量的值赋给在同一批中的局部变量,以便保存和作进一步处理

3.3.2.2 全局变量举例
n举例
select @@version
declare @book_price money
select @book_price = price from titles
where title_id = 'BU1032'
if @@rowcount = 0
print 'no such title_id'
else
begin
print 'title_id exists with'
select 'price of' = @book_price
end
4 存储过程中的流程控制语言
n流程控制SQL语句的执行顺序,这在存储过程、触发器、批中非常有用。流控制关键字(命令)包括:
na.IF ELSE
nb.IF EXISTS IF NOT EXISTS
nc.BEGINEND
nd.RETURN
ne.WHILE
nf.BREAKCONTINUE
ng.WAITFOR
nh.PRINT
4.1 IF ELSE
n部分语法(ASE)
if boolean_expression
     statement
[else [if boolean_expression1]
    statement1 ]
n部分语法(IQ)
if boolean_expression then
    statement
[else [if boolean_expression1]
statement1 ]
    End if
4.2 IF EXISTS IF NOT EXISTS
n功能
当你关心数据是否存在时,在IF语句中使用[NOT] EXISTS是很有用的。
n语法(ASE)
 if [not] exists (select statement)
    statement block
4.3 BEGINEND
n功能
当需要将一个以上的SQL语句作为一组语句对待时,可以使用BEGINEND将它们括起来形成一个SQL语句块。从语法上看,一个SQL语句块相当于一个SQL语句。在流控制语言中,允许用一个SQL语句块替代单个SQL语句出现的地方。
n语法
BEGIN
    statement block
END
这里:
statement block通常为一个以上的SQL语句。当然也可是一个SQL语句。
4.4 RETURN
n功能
   RETURN命令无条件退出它所在的批、存储过程或触发器。退出时,能选择提供返回状态。RETURN语句之后的任何语句不被执行。
n语法
RETURN [integer_expression]
n举例
if not exists ( select * from titles where title_id = @t_id)
begin
     print 'here is no title by this title_id'
     return --无条件退出批,其后语句不被执行。
     insert salesdetail values
     (@s_id, @o_num, @t_id,@qty_sold, @disc)
end
go
4.5 WHILE
n语法(ASE)
        while boolean exprission
            statement block
n语法(IQ)
   while boolean exprission loop
            statement block
        end loop
n举例
   while (select avg(price) from titles) < $40
   begin
       select title_id, price from titles
                 where price > $20
       update titles set price = price + $2
   end
      select title_id, price from titles
      print "Too much for the market to bear"
4.6 BREAKCONTINUE
n功能
    BREAKCONTINU关键字控制在WHILE循环中语句块中语句的执行。
BREAK关键字将退出它所在的循环,继续执行后面的语句(即跳过从关键字BREAK到它所在循环结束END之间的所有语句)
CONTINU关键字使循环重新开始,即跳过任何在该循环内但在CONTINU关键字之后的语句。
n语法(ASE)
    WHILE boolean expression
    BEGIN
        statement1
        statement2
        BREAK
        CONTINU
    END
    statement
n举例(ASE)
while (select avg(price) from titles) >= $20
begin
    update titles set price = price / 2
    if (select max(price) from titles) < $40
        break
    else
        if (select avg(price) from titles) < $20
            continu
        print "Average price still over $20"
end
print "Not too expensive.or Average price under $20"
4.7 WAITFOR
n功能
   WAITFOR关键字将挂起当前的执行, 直到指定的事件发生。它常常被系统用来实现有规律的系统维护、出错处理、事件处理和统计记录等。
n部分语法
   waitfor {delay time | time time |...}
n举例
这个例子是一个无终止循环,它每隔半小时记录一次锁的个数。
while 2>1   /* 这一表达式总是返回'TRUE' */
     waitfor delay '0:30:00'   /* 每隔30分钟 */
     insetrt into num_procs
     select getdate(), count(*)   from master, syslocks
4.8 PRINT
n功能
    PRINT关键字用来在屏幕上显示用户定义的
信息,局部变量的值或char/varchar类型的全
局变量的值。
n语法
    print {"any ascii characters or string"
    |local_variable | global_variable }
    [, arg_list ]
n举例
(1) print "hello"
(2) print @msg   /* @msg 是一个局部变量。 */
(3) declare @table_name varchar(30) , @user_name varchar(30)
   select @table_name = "titles", @user_name = "ezekiel"
   print "The table%1! is not owned by the user %2!",@table_name ,@user_name
5 存储过程中的事务、游标
n存储过程中的事务
n存储过程中的游标
5.1 嵌套事务
n嵌套事务 是指在存储过程中的事务的间接嵌套, 即嵌套事务的形成是因为调用含有事务的过程。@@trancount 记录了事务嵌套级次。@@trancount在第一个begin tran语句后值为1,以后每遇到一个 begin tran 语句,不论是否在嵌套过程中,@@trancount的值增加1;每遇到 一个commit,@@trancount的值就减少1。若@@trancount的 值 等于 零,表示当前没有事务;若@@trancount的值不等于零,其值 假定为i,表明当前处于第 i 级嵌套事务中。对于嵌套事务,直 到使用@@trancount 的值为零的那个 commit语句被执行,整个 事务才被提交。
 select   @@trancount
举例:在存储过程中的事务嵌套
5.1.1 与事务相关的语句
nRollback
 根据SQL Server的缺省规定,一个不带事务名或保存 点名的 rollback tran 语句,不论它是否在嵌套事务中,   总是退到最外面的 begin tran语句,即回退包括所有 嵌套事务在内的整个事务
ncommit
 根据SQL Server的缺省规定,即使是在嵌套事务中 执行commit 语句,@@trancount计数值也只减少1。
5.2 存储过程中的游标
n语法
create proc procedure_name
as
SQL_statements containing cursor processing
其中:SQL_statements containing cursor processing
是指包含游标处理的SQL语句。
n举例
create proc proc_fetch_book
As
begin
    declare @book_title char(30), @book_id char(6)
    declare biz_book cursor for
    select title, title_id from titles
        where type = "business"
    open biz_book
    fetch biz_book into @book_title, @book_id
           。。。    -- 在这里做某些处理
    close biz_book
    deallocate cursor biz_book
 return
end
n游标的作用域 如果存储过程是嵌套的话,那么也包括它的所有子域。这就是说,如果嵌套的存储过程构成一棵调用树(Call Tree),那么在这棵 树的某个结点上定义的游标,其作用域就是它位于的树叉,即自定义游标的那个结点的存储过程及它所包含的所有子域。但是如果在它所包含的子域中,定义了与它同名的游标,那么它将在定义同名游标的子域内及该子域所包含的其他子域内失效。
6 ASE存储过程和IQ存储过程常见区别、举例
n1.COMMIT – 在IQ存储过程中,每一个增、删、改、查的上sql后都要加上一个commit以保证语句成功执行(ASE不用)
n2.BEGIN END – ASE的存储过程的每个程序分支要放在BEGIN END中(每个条件判断,每个循环等),而IQ不用,只要在程序最外边有个BEGIN END 就可以了
n3.ASE存储过程要在存储过程名之后,BEGIN之前加上AS,IQ不用
n变量定义 – ASE DECLARE @ date_begin CHAR(8);
              IQ DECLARE date_begin CHAR(8);
n4.变量赋值 - ASE存储过程中:select @sql_str = ‘1’
             IQ存储过程中: select‘1' into sql_str
n5.变量引用 - ASE存储过程中:@+变量名
             IQ存储过程中:变量名

 

 

 

posted on 2013-12-19 16:07  canyue  阅读(779)  评论(0编辑  收藏  举报