存储过程,游标,异常捕捉 try catch 实例代码

 

大笑

1.存储过程代码。  (数据库是 AdventureWorks)

 

存储过程用来将错误信息插入到指定的表中。

在别的地方可以调用存储过程插入错误信息(下面部分代码 生成一个表,如果表已经存在就会插入错误信息到表中)

知识点: try catch,output参数;begin try..end try;begin catch….end catch;

--存储过程output, begin try,begin catch

 
  
 
  
--声明一个存储过程 uspLogErrorTest  模仿 uspLogError.用来记录发生错误的信息,并将错误信息

--放入到  select * from  [dbo].[ErrorLog]

 
  
create proc dbo.uspLogErrorTest

    @ErrorLogID [int]=0 output

    

AS

BEGIN

    set nocount on

    

    --输出参数

    set @ErrorLogID=0;

    

    Begin Try

        if error_number() is null     --捕捉错误号,有就激活catch

            return;

        

        --当前请求具有活动的用户事务,但出现了致使事务被归类为无法提交的事务的错误。

        --请求无法提交事务或回滚到保存点;它只能请求完全回滚事务。请求在回滚事务之前无法执行任何写操作。请求在回滚事务之前只能执行读操作。事务回滚之后,请求便可执行读写操作并可开始新的事务。

 
  
        if xact_state()=-1 

        begin 

            print 'Cannot log error since the current transaction is in an uncommittable state'

                  +' Rollback the transaction before executing uspLogError2 in order to successfully log error information'

            return;

        end

        

        insert [dbo].[ErrorLog]

            (

              [UserName],

              [ErrorNumber],

              [ErrorSeverity],

              [ErrorState],

              [ErrorProcedure],

              [ErrorLine],

              [ErrorMessage]

        

            )          

        values

            (

             convert(sysname,current_user),

             error_number(),

             error_severity(),

             error_state(),

             error_procedure(),

             error_line(),

             error_message()

            

            

            );

            

            

            --得到刚才插入的行号

            

            set @ErrorLogID=@@IDENTITY;

    end try

    begin catch

        print 'an error occurred in stored procedure uspLogError : '

        exec   [dbo].[uspprinterror];

        return -1;

    end catch

end

 
  
--select * from  [dbo].[ErrorLog]

 
  
 
  
 
  
--上面声明存储过程

 
  
--下面调用存储过程,创建表,如果已经存在就会写入表 [dbo].[ErrorLog]

use AdventureWorks

go

begin try

    create table OurIFTest(

        coll int primary key

    )

end try

 
  
begin catch

    --something wrong

    

    declare @MyOutputParameter int;

    

    if error_number()=2714    --object 存在的错误

    begin

        print     'waring: skipping CREATE AS table 已经存在'

        

        --执行刚才的存储过程

        

        exec  dbo.uspLogError @ErrorLogID=@MyOutputParameter output;  --执行,插入error表

        print '发生一个错误。错误id'+cast(@MyOutputParameter as nvarchar);

    end

    

    else

       raiserror('something not good happend this time around',16,1)

end catch

 

 

 

2.游标代码

本代码声明游标为global变量,在存储过程声明了游标,打开游标,但是唯独没close(关闭游标) 和 deallocate(清除游标分配到的内存)

游标各中关键字使用 gloal/local;   static/dynmic/keyset/fast_forward

static:不能感知原始表中数据的变化;存放在tempdb中

dynmic:能感知;但是占用大量性能

keyset:原始表必须有唯一索引,关键索引存在于tempdb中,能感知 删除,修改,不能感知新增的。

use AdventureWorks

go

create proc  spCursorScope2

AS

 
  
declare @Counter  int;

declare @OrderId  int;

declare @CustomerId int

 
  
declare CursorTest  cursor

Global--默认,即使不填。   Glbal/local

--<static,dynamic,keySet,Fast_forward>

For

	select SalesOrderId,CustomerID 

	from Sales.SalesOrderHeader

 
  
select @Counter=1;

 
  
open  CursorTest

fetch next from CursorTest into @OrderId,@CustomerId

print 'Row '+cast(@Counter as nvarchar)+' has a SalesOrderId of '+convert(nvarchar,@OrderId)+' and a CustomerId of '+cast(@CustomerId as nvarchar)

 
  
while(@@FETCH_STATUS=0) AND (@Counter<5)

begin

		select @Counter=@Counter+1;

		fetch next from CursorTest into @OrderId,@CustomerId

		print 'Row '+cast(@Counter as nvarchar)+' has a SalesOrderId of '+convert(nvarchar,@OrderId)+' and a CustomerId of '+cast(@CustomerId as nvarchar)

 
  
end

 
  
 
  
--上面的存储过程没有 close cursor ,和销毁 deallocate cursor

 
  
exec spCursorScope2

 
  
 
  
 
  
--重新声明几个变量,因为上面只有游标变量CursorTest 是全局的,其他的在存储过程外都要重新声明

--一旦执行存储过程,则游标就执行了,而且没关闭之前一直在内存中。则存储过程后面的语句可以继续使用上面的游标

exec spCursorScope

declare @OrderId   int

declare @CustomerId int

declare @Counter int

 
  
set @Counter=6

 
  
while (@@FETCH_STATUS=0) AND (@Counter<=10)

begin

		fetch next from CursorTest into @OrderId,@CustomerId

		print 'Row '+cast(@Counter as nvarchar)+' has a SalesOrderId of '+convert(nvarchar,@OrderId)+' and a CustomerId of '+cast(@CustomerId as nvarchar)

		set @Counter=@Counter+1

end

 
  
 
  
close CursorTest

deallocate CursorTest






3.事务 (tran)

Begin tran mytran; (名字可无)
commit tran xx;
rollback tran xx;
save tran xx; //将此出标记为回滚点。 rollback tran 回滚点名字;就会回滚到回滚点和回滚方法之间,其他地方不会回滚的。

例:

Begin tran mytran;
  declare @i int
  set @i=0

insert into students (name,sex) values ('小明',0)
save tran xiaoming;
 insert into students (name,sex) values ('小龙',0)
 save tran xiaolong;


rollback xiaoming; //回滚到xiaoming 回滚点

commit tran mytran; //此时数据库里只有小明,没有小龙的数据。

你可能感兴趣的:(catch)