存储过程调用多个存储过程
当为一个存储过程调用多个存储过程时,这是在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
我强烈建议使用TRY/CATCH块和RAISERROR而不是@@ ERROR/@结果检查。我有一个博客条目,显示如何正确使用交易和TRY/CATCH块,包括嵌套事务以仅恢复失败的过程调用工作,以便如果感觉如下:Exception Handling and Nested Transactions,则可以恢复不同的路径并继续交易。
<更新>
您现在的位置对于程序不一致的返回模式。 UpdateTHIS和UpdateTHAT返回0/1作为返回值,而包装DoStuff作为结果集返回(SELECT)。这意味着您无法编写调用DoStuff的DoMoreStuff,因为它必须使用INSERT ... EXEC捕获结果,并且您将很快发现INSERT ... EXEC无法嵌套。为了保持一致性,我建议使用RETURN @result。
< /更新>
我也有一个不相关的表彰,这只是风格的元素:我觉得长IF ... ELSE IF ... ELSE IF ... ELSE IF ...块难以阅读和遵循。我总是发现,表达与DO相同... BREAK ... BREAK ... BREAK ... WHILE(FALSE)更容易阅读。 T-SQL没有DO ... 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
同样,这也不重要,因为仅仅是一个代码格式化的风格,但它是一个如果您同意这会导致代码更容易阅读,那么建议您。
恕我直言,我不认为从一个存储过程调用其他存储过程是一个非常好的主意。如果出现错误,需要花费大量的人工时间才能找出错误发生的位置。在某些情况下,另一个开发人员可能会更改存储的proc而不告诉团队中的任何人。可能出错的事情太多了。
可能最好将所有的sql写入一个大的存储过程。
编辑: 这也取决于你的存储过程将会有多大。
但费用是多少?在重构为多个存储过程之后,我维护一次的数千行存储过程被削减为一行或两百行代码。使存储过程独立存在会大大增加在存储过程中发现的重复代码量。 – MatthewMartin 2009-11-11 16:11:40
的确,我不得不同意它取决于存储过程的大小。 – iJK 2009-11-11 16:18:17
我完全不同意。重复在多个存储过程中执行相同操作的代码将是一种不好的编程习惯。存储过程专门用于封装业务或数据逻辑,以便可以重用。 虽然从另一个层次调用存储过程存在一些限制,但维护的好处大大超出了风险。就像应用程序中的任何“共享”组件(如DLL或Web服务等)一样,更改后的兼容性是一个重要问题,但它远不是一个大问题...... – JFTxJ 2013-09-16 14:06:11
嵌套ifs和不嵌套ifs不同。回滚将回滚一个事务,但继续。我有一些明确的RETURN命令来保证,并明确何时何地你想让代码退出存储过程。
看起来不错,除了我会为每个IF和ELSE – 2009-11-11 16:04:35
r IFs嵌套?...如果他们r然后我宁愿使用BEGIN和END在我们的逻辑写他们... ...使用显式BEGIN和END ... – deostroll 2009-11-11 16:06:55