为一个存储过程调用多个存储过程时,这是在SQL Server 2008上进行此操作的正确或最佳方法吗?
CREATE PROCEDURE [dbo].[DoStuff]
AS
BEGIN
SET NOCOUNT ON;
declare @result int
BEGIN TRANSACTION
BEGIN
EXECUTE @result = dbo.UpdateTHIS @ID = 1
IF @result != 0
ROLLBACK
ELSE
EXECUTE @result = dbo.UpdateTHAT @ID = 21
IF @result != 0
ROLLBACK
ELSE
EXECUTE @result = dbo.UpdateANOTEHR @ID = 15
IF @result != 0
ROLLBACK
ELSE
COMMIT
SELECT @result
END
END
答案 0 :(得分:5)
我强烈建议使用TRY / CATCH块和RAISERROR而不是@@ ERROR / @结果检查。我有一个博客条目,显示如何正确使用事务和TRY / CATCH块,包括嵌套事务只恢复失败的过程调用工作,以便calee可以恢复不同的路径并继续事务,如果它感觉像:{{ 3}}
<强>&LT;更新&GT; 强>
您在程序退货模式方面存在不一致之处。 UpdateTHIS和UpdateTHAT返回0/1作为返回值,而包装器DoStuff作为结果集(SELECT)返回。这意味着您无法编写调用DoStuff的DoMoreStuff,因为它必须使用INSERT ... EXEC来捕获结果,并且您很快就会发现INSERT ... EXEC无法嵌套。为了保持一致性,我建议使用RETURN @result。
&LT; /更新&GT;
我也有一个不相关的推荐,这只是风格的一个元素:我发现很长的IF ...如果......如果......如果......如果...块很难阅读和遵循。我总是发现表达与DO一样...... BREAK ...... BREAK ...... BREAK ...... WHILE(FALSE)更容易阅读。 T-SQL没有DO ... WHILE构造,因此必须使用WHILE ...:
BEGIN TRANSACTION
WHILE (1=1)
BEGIN
EXECUTE @result = dbo.UpdateTHIS @ID = 1;
IF @result != 0
BEGIN
ROLLBACK;
BREAK;
END
EXECUTE @result = dbo.UpdateTHAT @ID = 21
IF @result != 0
BEGIN
ROLLBACK;
BREAK;
END
...
COMMIT;
BREAK;
END
同样,这并不重要,因为它只是一种代码格式化风格,但如果您同意它会导致代码更容易阅读,那么这是一个建议。
答案 1 :(得分:1)
嵌套ifs与否/嵌套ifs不同。回滚将回滚一个事务,但继续。我有一些显式的RETURN命令来保证,并在你希望代码退出存储过程的时间和地点显而易见。
答案 2 :(得分:-1)
最好在一个大的存储过程中编写所有sql。
编辑: 它还取决于存储过程的大小。