如果在另一个存储过程中调用存储过程,是否可以获取?

问题描述 投票:1回答:4

我有2个存储过程,第一个调用事务中的第二个存储过程。永远不应该直接调用第二个过程,而只能从其父级中调用。

目前,要检查是否是这种情况,我在第二个过程中执行以下操作:

DECLARE @inTran bit;
IF @@TRANCOUNT > 0
    SET @inTran= 0
ELSE
    SET @inTran= 1

它是否正确?有一个更好的方法吗?

sql-server sql-server-2017
4个回答
2
投票

如果你只是在寻找一种随意的方法来防止无意中执行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中读取的值。

这些都不会阻止某些人为了规避这些限制而无法按照预期运行。他们只会防止意外滥用。


0
投票

没有可靠的方法来做到这一点。检查@@ trancount只会在您进行交易时为您提供信息,有人可以这样做:

BEGIN TRAN
EXECUTE nested_proc_directly

在这种情况下,proc中的tran计数将大于0。并且正如其他人所说的那样,你不能调用堆栈。非常抱歉。


0
投票

我正在这里读一下这些线,并猜测实际的问题是如何阻止Procedure2被任何进程运行,除了来自Procedure1的调用。

如果必须尽可能接近完全锁定,请创建专用服务帐户以运行这些过程或其关联的作业,然后仅将EXECUTEProcedure2权限授予该专用帐户。

如果“非常锁定”足够好,只需将EXECUTEProcedure2权限授予您在生产中运行作业的服务帐户。至少这会让流浪的用户不再犹豫不决。

另一个想法是创建一个包含两个Execute SQL Tasks的SSIS包,第一个包含Procedure1中的所有代码,第二个包含Procedure2中的所有代码,然后取消procs并运行包。但是,我并不关心在代码中嵌入代码,因为维护很烦人。


0
投票

你可以使用@@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
© www.soinside.com 2019 - 2024. All rights reserved.