看看这个网上流传的“sql server 事务举例”

CREATE PROCEDURE testPro
AS
    
/* ------- 事务开始 ---------- */
    
BEGIN TRANSACTION tran_test

    
/* -------- 保存事务 ----------*/
    
SAVE TRANSACTION tran_test

        
/* -------- 数据操作 ---------*/
        
INSERT [table1] ( [content] ) VALUES ( '43332' )

    
/*---------- 提交事务 ------------*/
    
COMMIT TRANSACTION tran_test

    
/*--------- 判断是否有错误 ----------*/
    
IF ( @@ERROR <> 0 )
    
BEGIN
        
/*---------- 自定义错误输出 ----------*/
        
RAISERROR'Insert data error!',16,1 )
        
/*-------- 事务回滚 --------*/
        
ROLLBACK TRANSACTION tran_test
    
END
    
    
/*------- 判断事务数是否大于0 -----------*/
    
IF ( @@TRANCOUNT > 0 )
    
BEGIN
        
/*-------- 事务回滚 --------*/
        
ROLLBACK TRANSACTION tran_test
    
END
GO


这个在网上流传的存储过程事务举例我也用过,可是今天拿出来一看,已经提交的事务还能回滚吗?

从直观上就是错误的,俺以为其中另有“隐情”,于是作了个测试,测试代码如下:

先建了一个表,并向其中添加了约束:

USE [test]
GO
/****** 对象:  Table [dbo].[salary]    脚本日期: 12/12/2007 14:24:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[salary](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [salary] [real] NULL
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[salary]  WITH NOCHECK ADD  CONSTRAINT [t1] CHECK  (([salary]>=(1) AND [salary]<=(1)))
GO
ALTER TABLE [dbo].[salary] CHECK CONSTRAINT [t1]


然后新建了一个存储过程:

USE [test]
GO
/****** 对象:  StoredProcedure [dbo].[tt]    脚本日期: 12/12/2007 14:25:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:  <风景年华>
-- Create date: <2007-12-12>
-- Description: <test>
-- =============================================
CREATE PROCEDURE [dbo].[tt]
 -- Add the parameters for the stored procedure here
AS
BEGIN
 -- SET NOCOUNT ON added to prevent extra result sets from
 -- interfering with SELECT statements.
 SET NOCOUNT ON;

    -- Insert statements for procedure here
 begin tran
  save tran test
  insert salary values (5)
 
 if (@@error<>0)
  begin
   print '111'
   rollback tran test
  end
 commit tran

 END

再建一个存储过程:

USE [test]
GO
/****** 对象:  StoredProcedure [dbo].[tt]    脚本日期: 12/12/2007 14:25:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:  <风景年华>
-- Create date: <2007-12-12>
-- Description: <test>
-- =============================================
CREATE PROCEDURE [dbo].[tt1]
 -- Add the parameters for the stored procedure here
AS
BEGIN
 -- SET NOCOUNT ON added to prevent extra result sets from
 -- interfering with SELECT statements.
 SET NOCOUNT ON;

    -- Insert statements for procedure here
 begin tran
  save tran test
  insert salary values (5)
 
  commit tran

if (@@error<>0)
  begin
   print '111'
   rollback tran test
  end

 END

两次测试结果:
1.

消息 547,级别 16,状态 0,过程 tt,第 17 行
INSERT 语句与 CHECK 约束"t1"冲突。该冲突发生于数据库"test",表"dbo.salary", column 'salary'。
语句已终止。
111

(1 行受影响)

结果中输出了  111

2.

消息 547,级别 16,状态 0,过程 tt1,第 17 行
INSERT 语句与 CHECK 约束"t1"冲突。该冲突发生于数据库"test",表"dbo.salary", column 'salary'。
语句已终止。

(1 行受影响)

结果中没有输出  111  表明没有执行存储过程

测试环境:sql  server  2005 express

这是另外一个示例:

1,SqlServer存储过程的事务处理
一种比较通用的出错处理的模式大概如下:
Create procdure prInsertProducts
(
 @intProductId int,
 @chvProductName varchar(30),
 @intProductCount int
)
AS
Declare @intErrorCode int
Select @intErrorCode=@@Error
Begin transaction
 if @intErrorCode=0
   begin
     -insert products
     insert products(ProductID,ProductName,ProductCount)
     s(@intProductId,@chvProductName,@intProductCount)
     Select @intErrorCode=@@Error --每执行完一条t-sql语句马上进行检测,并把错误号保存到局部变量中
   end
 if @intErrorCode=0
   begin
     -update products
     update products set ProductName='MicroComputer' where ProductID=5
     Select @intErrorCode=@@Error
   end
if @intErrorCode=0
   commit transaction
else
   rollback transaction

 Return @intErrorCode --最好返回错误代号给调用的存储过程或应用程序

2,.Net中使用事务处理
SqlConnection myConnection = new SqlConnection("Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;");
myConnection.Open();

SqlTransaction myTrans = myConnection***ginTransaction(); //使用New新生成一个事务
SqlCommand myCommand = new SqlCommand();
myCommand.Transaction = myTrans;

try
{
myCommand.CommandText = "Update Address set location='23 rain street' where userid='0001'";
myCommand.ExecuteNonQuery();
myTrans.Commit();
Console.WriteLine("Record is udated.");
}
catch(Exception e)
{
myTrans.Rollback();
Console.WriteLine(e.ToString());
Console.WriteLine("Sorry, Record can not be updated.");
}
finally
{
myConnection.Close();
}


说明:在SqlServer中,每条Sql语句都作为一个事务来执行,所以无论在存储过程,还是在.net代码中使用,执行单条Sql语句没有必要使用事务处理,上面只是为了简化表达而对单条Sql语句使用事务处理



这就是俺的测试  初学sql  欢迎拍转

posted @ 2007-12-12 14:34  小弱  阅读(830)  评论(0编辑  收藏  举报