我正在尝试使一个长存储过程更易于管理,有一个调用其他存储过程的存储过程是错误的,例如我想要一个将数据插入表中的sproc并根据类型在表格中插入其他信息,例如:
BEGIN TRANSACTION
INSERT INTO dbo.ITSUsage (
Customer_ID,
[Type],
Source
) VALUES (
@Customer_ID,
@Type,
@Source
)
SET @ID = SCOPE_IDENTITY()
IF @Type = 1
BEGIN
exec usp_Type1_INS @ID, @UsageInfo
END
IF @TYPE = 2
BEGIN
exec usp_Type2_INS @ID, @UsageInfo
END
IF (@@ERROR <> 0)
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
或者这是我应该在我的申请中处理的事情吗?
答案 0 :(得分:12)
我们一直调用其他过程中的过程。否则,很难/不可能分割数据库密集型(或仅限数据库)的应用程序。
答案 1 :(得分:9)
从另一个程序内部调用程序是完全可以接受的。
但是,在依赖于@@ ERROR的Transact-SQL中容易出现故障。例如,您的代码。它将无法检测到插入失败,以及在被调用过程中产生的任何错误。这是因为@@ ERROR在每个语句执行时被重置,只保留最后一个语句的结果。我有一个博客条目,显示correct template of error handling in Transact-SQL和事务嵌套。 Erland Sommarskog也有一篇文章,很长一段时间,reference read on error handling in Transact-SQL。
答案 2 :(得分:4)
不,这完全可以接受。
答案 3 :(得分:4)
当然,没有。
我已经看到了大量的存储过程,这些存储过程执行了20个不同的事情,这些事情本来可以从重构为更小的,单一用途的事情中获益。
答案 4 :(得分:3)
只要它在同一个DB模式中,我认为是完全可以接受的。重复使用总是有利于复制。这就像在某个应用程序层中调用方法一样。
答案 5 :(得分:3)
完全没有,我甚至会说,建议你出于与在代码中创建方法相同的原因
答案 6 :(得分:3)
调用另一个存储过程的一个存储过程很好。只是你的筑巢水平有限,你可以去。
在SQL Server中,@@NESTLEVEL
函数返回当前嵌套级别。
请在此处查看存储过程嵌套部分http://msdn.microsoft.com/en-us/library/aa258259(SQL.80).aspx
欢呼声
答案 7 :(得分:2)
没有。它促进了重用,并允许将功能组件化。
答案 8 :(得分:2)
正如其他人所指出的,这是完全可以接受和必要的,以避免重复功能。
但是,在Transact-SQL中注意嵌套存储过程调用中的事务:您需要在发出@@TRANCOUNT
之前检查rollback transaction
,因为它会回滚所有嵌套事务。请查看此article以获得深入的解释。
答案 9 :(得分:1)
在我们的IT领域,我们使用存储过程来整合存储过程和触发器的公共代码(如果适用)。它几乎也是避免SQL源重复的必要条件。
答案 10 :(得分:1)
这个问题的一般答案当然是否 - 这是编写SQL存储过程的正常甚至首选方式。
但可能在你的具体情况下,这不是一个好主意。
如果您在应用程序(Java,.Net等)中维护一组支持数据访问层(DAO)的存储过程,那么使用数据库层(让我们以这种方式调用存储过程)简化并相对较薄将有益于您的整体设计。因此,具有存储过程调用的大量图可能确实对于维护和支持这种应用中的整体数据访问逻辑是不利的。
我倾向于在DAO和数据库层之间更加统一地分配逻辑,以便存储过程代码适合单个函数调用。
答案 11 :(得分:1)
是的,这很糟糕。虽然SQL Server支持并允许一个存储过程调用另一个存储过程。如果可能的话,我通常会尽量避免这种设计。我的理由?
答案 12 :(得分:0)
添加其他海报的正确评论,原则上没有任何错误,但是如果外部应用程序正在调用该过程,则需要注意执行时间。符合特定的超时。
典型示例,如果从 Web应用程序调用存储过程:当默认超时启动时,因为您的执行链需要更长时间,即使存储过程提交,Web应用程序也会出现故障正确。 如果从外部服务呼叫,也会发生同样的情况。 这可能会导致应用程序中的行为不一致,从而触发外部服务中的错误管理例程等。
如果您遇到这样的情况,我所做的就是打破使用 Service Broker 将长执行子调用重定向到不同进程的调用链。