只是想知道以下是否是编写使用BEGIN TRANSACTION的SQL脚本的正确方法? (像DML一样的东西)
BEGIN TRY
BEGIN TRANSACTION
/* SQL statements here */
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@ERROR <> 0
ROLLBACK TRANSACTION
END CATCH
每当我尝试在SQL服务器中执行它时,脚本都会运行但不知何故它不会提交事务。我仍然需要使用COMMIT TRANSACTION手动提交。
在我的SQL Server Management Studio 2012中,我检查了SET_IMPLICIT_TRANSACTIONS以避免在开发脚本时自动提交。但是因为如果所有语句都成功运行,我已经把语句COMMIT TRANSACTION放了,那么右边我的脚本应该自动提交吗?除非我在这里弄错了。
答案 0 :(得分:1)
您的IF @@ERROR <> 0
区块中不需要CATCH
。当控制转移到CATCH块时,意味着发生了错误。你可以直接做这样的回滚
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
如果需要,您可以使用XACT_STATE()
检查交易状态。
在catch块中,您可以在某些表中记录错误,或者根据您的要求和您正在使用的sql server版本,使用THROW
或RAISERROR
来修复错误。
修改强>
当您IMPLICIT_TRANSACTIONS ON
vs IMPLICIT_TRANSACTIONS OFF
根据IMPLICIT_TRANSACTIONS ON
的{{3}}:
当IMPLICIT_TRANSACTIONS = ON时,显式BEGIN TRANSACTION将启动两个嵌套事务。
脚本的测试表
CREATE TABLE test_table( a int)
使用SET IMPLICIT_TRANSACTIONS OFF
和SET IMPLICIT_TRANSACTIONS ON
BEGIN TRANSACTION
SELECT @@TRANCOUNT
INSERT INTO test_table VALUES(1)
SELECT @@TRANCOUNT
COMMIT
SELECT @@TRANCOUNT
使用SET IMPLICIT_TRANSACTIONS OFF
输出
-----------
1
-----------
1
-----------
0
使用SET IMPLICIT_TRANSACTIONS ON
输出
-----------
2
-----------
2
-----------
1
因为当SET IMPLICIT_TRANSACTIONS ON
有2个打开的事务而且只有一个提交时,似乎提交事务没有做任何事情。
有关错误处理的更多信息,请参阅以下参考链接:
Erland Sommarskog的3部分系列msdn
Robert Sheldon关于Error Handling的文章
答案 1 :(得分:0)
使用此代码:
BEGIN TRANSACTION
BEGIN TRY
/* SQL statements here */
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
因为你的Sql语句在里面运行
Begin..end try block:
1)如果没有错误发生,它会自动执行提交事务并退出尝试阻止。
2)如果 TRY BLOCK 中的语句出错,它会直接跳转到 BEGIN CATCH 块,并使用 ROLLBACK TRANSACTION 放置那里的整个事务回滚在 CATCH BLOCK 中显示错误消息的类型。
使用此代码不需要手动提交事务。 如果没有错误,它会自动提交。