SQL Server事务如何提交我的事务

时间:2010-05-20 18:08:21

标签: sql sql-server sql-server-2005

我有SQL Server 2005存储过程。有人在事务中调用我的存储过程。在我的存储过程中,我正在记录一些信息(插入表中)。当更高级别的事务回滚时,它会删除我的插入。

无论如何,我可以提交我的插入并阻止更高级别的回滚删除我的插入?

由于

4 个答案:

答案 0 :(得分:6)

即使您启动新事务,它也将嵌套在外部事务中。 SQL Server保证回滚将导致未修改的数据库状态。因此,您无法在中止的事务中插入行。

这是一种绕过它的方法,这是一个小技巧。使用rpc out = trueremote proc transaction promotion = false创建链接服务器。链接的服务器可以指向运行过程的同一服务器。然后,您可以使用execte (<query>) at <server>在新事务中执行某些操作。

if OBJECT_ID('logs') is not null drop table logs
create table logs (id int primary key identity, msg varchar(max))
if OBJECT_ID('TestSp') is not null drop procedure TestSp
go
create procedure TestSp as
execute ('insert into dbo.logs (msg) values (''test message'')') at LINKEDSERVER
go
begin transaction
exec TestSp
rollback transaction
select top 10 * from logs

即使事务已回滚,这也会在日志表中以一行结束。

以下是创建此类链接服务器的示例代码:

IF  EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND 
        srv.name = N'LINKEDSERVER')
    EXEC master.dbo.sp_dropserver @server=N'LINKEDSERVER', 
        @droplogins='droplogins'
EXEC master.dbo.sp_addlinkedserver @server = N'LINKEDSERVER', 
    @srvproduct=N'LOCALHOST', @provider=N'SQLNCLI', @datasrc=N'LOCALHOST', 
    @catalog=N'DatabaseName'
EXEC master.dbo.sp_serveroption @server=N'LINKEDSERVER', @optname=N'rpc out', 
     @optvalue=N'true'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'LINKEDSERVER', 
    @useself=N'True', @locallogin=NULL,@rmtuser=NULL, @rmtpassword=NULL
EXEC master.dbo.sp_serveroption @server=N'LINKEDSERVER', 
    @optname=N'remote proc transaction promotion', @optvalue=N'false'

答案 1 :(得分:3)

Oracle中,您会使用自动交易,但SQL Server不支持它们。

可以声明一个表变量并从存储过程中返回它。

表变量在ROLLBACK之后存在,但是,应修改上层代码以读取变量并永久存储其数据。

答案 2 :(得分:2)

根据权限,您可以使用xp_cmdshell调用OSQL,从而创建完全独立的连接。您可能能够使用CLR执行类似的操作,但我从未尝试过。但是,我强烈建议不要这样做。

最好的办法是确定代码和调用代码的约定 - 两者之间支持哪种类型的契约。您可以规定,您的代码永远不会在另一个事务中被调用(可能不是一个好主意),或者您可以对发生错误时调用代码负责的内容提出要求。

答案 3 :(得分:1)

交易中的任何内容都将成为该交易的一部分。如果您不希望它成为该交易的一部分,那么请不要将其放入。