0
我们正在尝试实施一个修补客户端软件的程序 - 最初将运行一个.SQL,但如果脚本在任何时候都失败,我们将回滚数据库并停止客户端DLL导入过程从工作。通过多个数据库上的事务执行SQL脚本
我们的SQL脚本具有“GO”语句,因此我们无法将使用sp_executesql
的漂亮存储过程放在一起,因为这不允许“GO” - 相反,如果我们有一个如下所示的SQL脚本:
USE [SomeDatabase]
BEGIN TRANSACTION
GO
IF (OBJECT_ID(N'[dbo].[ProcedureToUpdate]') IS NOT NULL)
DROP PROCEDURE [dbo].[ProcedureToUpdate]
GO
IF @@ERROR <> 0
AND @@TRANCOUNT > 0
ROLLBACK TRAN
GO
IF @@TRANCOUNT = 0
BEGIN
--Flag that the procedure hasn't been dropped, begin another transaction
BEGIN TRANSACTION
END
GO
PRINT 'Creating procedure'
GO
CREATE PROCEDURE [dbo].[ProcedureToUpdate]
AS
SELECT *
FROM [dbo].[SomeTable] st
INNER JOIN [dbo].[AnotherTable] at ON st.PK = at.fk
GO
IF @@ERROR <> 0
AND @@TRANCOUNT > 0
ROLLBACK TRAN
GO
IF @@TRANCOUNT = 0
BEGIN
--Flag that the procedure hasn't been created, begin another transaction
BEGIN TRANSACTION
END
GO
然后,我们正在执行在.NET中有问题的数据库事务中的每个“动作”(由go语句拆分) - 如果循环内部出现任何故障,这将回滚数据库。
Using con As New SqlConnection(ConnectionString)
con.Open()
Dim cmd As SqlCommand = con.CreateCommand()
Dim transaction As SqlTransaction = con.BeginTransaction("Upgrade")
cmd.Connection = con
cmd.Transaction = transaction
Try
For Each transactionalScript In transactionalScripts
cmd.CommandText = transactionalScript
Dim result = cmd.ExecuteNonQuery()
Next
transaction.Commit()
Catch ex As Exception
Log(String.Format("{0} : Script Failed", DateTime.Now.ToString()))
Log(String.Format("{0} : Reason: {1}", DateTime.Now.ToString(), ex.Message))
transaction.Rollback("Upgrade")
Log(String.Format("{0} : Database rolled back", DateTime.Now.ToString()))
End Try
End Using
最后 - 这是我的问题。我们需要处理多达4个.SQL脚本,每个脚本将用于单个服务器上的不同数据库。如果4个脚本中的任何一个发生故障,我们应该回滚脚本受到影响的每个数据库 - 有什么建议吗?