2010-05-20 45 views
2

我有SQL Server 2005存儲過程。有人在事務中調用我的存儲過程。在我的存儲過程中,我正在記錄一些信息(插入到表中)。當更高級別的事務回滾時,它將刪除我的插入。SQL Server事務我如何提交我的事務

有無論如何我可以提交我的插入並防止更高級別的回滾刪除我的插入?

謝謝

回答

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' 
+0

Damm you SQL Server !!!!我需要漂亮的功能。 – codingguy3000 2010-05-20 18:13:01

+0

@ codingguy3000:找到了一個訣竅,回答編輯。這需要管理權限tho – Andomar 2010-05-20 19:21:43

1

任何一個事務內將是交易的一部分。如果您不希望它成爲該交易的一部分,那麼請不要放入其中。

+0

調用存儲過程正在啓動事務。所以我無法避免成爲這筆交易的一部分。 – codingguy3000 2010-05-20 18:14:34

+0

你能重新設計它的工作原理嗎?這聽起來像一個可憐的設計,一般 – 2010-05-20 20:56:08

3

Oracle您可以使用自動事務處理,但是,SQL Server不支持它們。

可以聲明一個表變量並從存儲過程中返回它。

表變量經歷了ROLLBACK,但是應修改上層代碼以讀取變量並永久存儲其數據。

+0

正是我想要建議的 – HLGEM 2010-05-20 18:25:30

2

根據權限,您可以使用xp_cmdshell調用OSQL來創建完全獨立的連接。你可能可以用CLR做類似的事情,儘管我從來沒有嘗試過。但是,我強烈建議不要這樣做。

最好的辦法是確定代碼和調用代碼的約定 - 兩者之間支持哪種合同。你可以規定你的代碼從來不會在另一個事務中被調用(可能不是一個好主意),或者你可以提供關於發生錯誤時調用代碼負責的要求。