测试代码: ADOQuery1.sql:='select * from region' ADOQuery2.sql:='exec SP_test'='select * from region'
ADOConnection1.BeginTrans; ADOQuery1.Post; //必需发送一次语句重新从数据库提取一次更新后的数据;个人认为同一进程(ADOConnection连接,在SQL Server为一个连接进程,或者一个会话),未提交数据也可以访问,但需人为重新发送一个语句以便从数据库中提出数据返回到数据集TDataSet ADOQuery2.Close; ADOQuery2.Open; ShowMessage(ADOQuery2.FieldByName('Name').AsString);
if CheckBox1.Checked then ADOConnection1.CommitTrans else ADOConnection1.RollbackTrans; //撤销事务时,因为ADOQuery1做为TDataSet中的数据为修改后,必需刷新一下,ADOQuery2因为修改后,事务提交前重新提过数据,所以现在必需再提一次撤销后数据 ADOQuery1.Close; ADOQuery1.Open; ADOQuery2.Close; ADOQuery2.Open;
执行跟踪产生的SQL语句与解读:
set implicit_transactions on 开始隐性事务 go exec sp_executesql N'UPDATE "public".."region" SET "Name"=@P1 WHERE "Code"=@P2 AND "Name"=@P3 AND "Postcode"=@P4 AND "AreaCode"=@P5 AND "Area"=@P6', N'@P1 varchar(7),@P2 varchar(6),@P3 varchar(12),@P4 varchar(2),@P5 varchar(3),@P6 varchar(4)', 'abdasdf', 'efasdf', '111111111111', 'as', 'asd', 'asdf' --ADOQuery1执行数据修改 go select * from region --ADOQuery2执行,这里可以提取到修改后数据,虽然没有提交 go IF @@TRANCOUNT > 0 COMMIT TRAN 提交事务或IF @@TRANCOUNT > 0 ROLLBACK TRAN回滚 go set implicit_transactions off 关闭隐性事务 go select * from region --ADOQuery1重新提取
go select * from region --adoquery2重新提取
go
注意: 1.Adoquery1和adoquery2使用同一个ADOConnection1 2.本事务未结束,则其它进程里无法读取region表数据
2005-11-4 11:55:39
2005-11-23 14:39:27 不能返回客户端ADOCONNECTION错误信息,但在查询分析器里可能看到
ALTER procedure SP_test as Begin Transaction T_SP_AlterFeeTable
select * from sysobjects
RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)
commit transaction T_SP_AlterFeeTable
2005-11-23 14:41:33 可以返回客户端ADOCONNECTION错误信息
ALTER procedure SP_test as Begin Transaction T_SP_AlterFeeTable
RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)
select * from sysobjects
commit transaction T_SP_AlterFeeTable
2005-11-23 14:44:22 能返回客户端ADOCONNECTION错误信息,但在查询分析器里可能看到
ALTER procedure SP_test as Begin Transaction T_SP_AlterFeeTable
select * from sysobjects
commit transaction T_SP_AlterFeeTable
RAISERROR ('修改核算数据表异常,系统将自动删除指定的工艺项目数据!', 16, 1)
2005-11-23 15:59:19 关于Raiserror与ADO分析结果
ADO调用执行存储过程的时都会(SET FMTONLY ON),比如,在ADOQuery2.sql中填入exec sp_test,则相应的程序调用以下代码: SET FMTONLY ON exec sp_test SET FMTONLY OFF 可见,只要在执行存储过程sp_test时发生异常,仅将元数据返回给客户端,且将不对行进行处理,也不将行作为请求的结果发送到客户端。而RAISERROR,PRINT产生的信息,都将不会返回客户端,但SQLSERVER产生的ERROR信息除外。并且SET FMTONLY在存储过程中全局有效,执行完后则无效。
由上可见,系统不包括的错误信息,比如业务安全检查,需要通过RAISERROR返回信息时,一定要在存储过程中SET FMTONLY OFF RAISERROR('错误',16,1)这样才能在客户端得到错误信息
2005-11-23 16:34:07 最后的测试代码
delphi+ado:
var i:Integer; begin try ADOConnection1.BeginTrans; ADOQuery1.Post; with ADOQuery2 do begin Close; SQL.Clear; SQL.Add('exec sp_test '); Open; end;
ADOConnection1.CommitTrans;
except for i:=0 to ADOConnection1.Errors.Count-1 do ShowMessage(ADOConnection1.Errors[i].Description); ADOConnection1.RollbackTrans; ADOQuery1.Close; ADOQuery1.Open; //ADOQuery2.Close; //ADOQuery2.Open; end;
下面是Query2调用存储过程代码
SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO /* SET FMTONLY ON exec sp_test SET FMTONLY OFF */ ALTER procedure SP_test as declare @sql nvarchar(1000),@FiledName varchar(128) select top 1 @FiledName='['+isnull(Name,'')+']' from Region
if rtrim(@FiledName)='[ ]' begin SET FMTONLY OFF RAISERROR ('指定的字段名不能空', 16, 1) return end
set @sql ='alter table tt add '+@FiledName+' int' Begin Transaction T_SP_AlterFeeTable
execute(@sql)
if @@ERROR<>0 begin ROLLBACK transaction T_SP_AlterFeeTable
select * from tt return end else begin
commit transaction T_SP_AlterFeeTable
select * from tt end
GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO
2005-11-23 16:57:39
for i:=0 to ADOConnection1.Errors.Count-1 do ShowMessage(ADOConnection1.Errors[i].Description);
用raise代替也能提示错误信息
var i:Integer; begin try ADOConnection1.BeginTrans; ADOQuery1.Post; with ADOQuery2 do begin Close; SQL.Clear; SQL.Add('exec sp_test '); Open; end;
ADOConnection1.CommitTrans;
except //for i:=0 to ADOConnection1.Errors.Count-1 do //begin // ShowMessage(ADOConnection1.Errors[i].Description); //end;
ADOConnection1.RollbackTrans; ADOQuery1.Close; ADOQuery1.Open; raise; //ADOQuery2.Close; //ADOQuery2.Open; end; end;
2005-11-23 17:20:08
只要DELPHI使用try+事务处理,其实就算调用了存储过程执行多步操作,也可以回滚,而不必在存储过程中额外进行事务处理,但如果想部分修改有效的话,就得不使用DELPHI的ADO事务,而使用数据库存储过程中处理事务也可以。
|