我有2个存储过程,第一个调用事务中的第二个存储过程。永远不应该直接调用第二个过程,而只能从其父级中调用。
目前,要检查是否是这种情况,我在第二个过程中执行以下操作:
DECLARE @inTran bit;
IF @@TRANCOUNT > 0
SET @inTran= 0
ELSE
SET @inTran= 1
它是否正确?有一个更好的方法吗?
如果你只是在寻找一种随意的方法来防止无意中执行proc。你也可以检查@@NESTLEVEL
- 如果从另一个proc调用,这将至少是2
。
CREATE PROCEDURE Child
AS
IF @@NESTLEVEL < 2 OR @@TRANCOUNT = 0
THROW 50000, 'Child proc should be called from Parent', 1;
或者你可以让父proc设置一个由SESSION_CONTEXT()
在子proc中读取的值。
这些都不会阻止某些人为了规避这些限制而无法按照预期运行。他们只会防止意外滥用。
没有可靠的方法来做到这一点。检查@@ trancount只会在您进行交易时为您提供信息,有人可以这样做:
BEGIN TRAN
EXECUTE nested_proc_directly
在这种情况下,proc中的tran计数将大于0。并且正如其他人所说的那样,你不能调用堆栈。非常抱歉。
我正在这里读一下这些线,并猜测实际的问题是如何阻止Procedure2
被任何进程运行,除了来自Procedure1
的调用。
如果必须尽可能接近完全锁定,请创建专用服务帐户以运行这些过程或其关联的作业,然后仅将EXECUTE
的Procedure2
权限授予该专用帐户。
如果“非常锁定”足够好,只需将EXECUTE
的Procedure2
权限授予您在生产中运行作业的服务帐户。至少这会让流浪的用户不再犹豫不决。
另一个想法是创建一个包含两个Execute SQL Tasks
的SSIS包,第一个包含Procedure1
中的所有代码,第二个包含Procedure2
中的所有代码,然后取消procs并运行包。但是,我并不关心在代码中嵌入代码,因为维护很烦人。
你可以使用@@PROCID。唯一的问题是你需要通过输入传递参数。
CREATE PROCEDURE usp_Test1(@id As int)
AS
PRINT @id
PRINT OBJECT_NAME(@id)
GO
CREATE PROCEDURE usp_Test2
AS
EXEC usp_Test1 @@PROCID
GO
EXEC usp_Test2
GO
产量
1054730910
usp_Test2