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 歡迎拍轉