是否有可能在另一个存储过程中调用存储过程?

时间:2019-04-09 10:59:29

标签: sql-server sql-server-2017

我有2个存储过程,其中第一个在事务中调用第二个。第二个过程绝对不能直接调用,而只能在其父内部调用。

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

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

这是正确的吗?有更好的方法吗?

4 个答案:

答案 0 :(得分: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在子proc中设置一个SESSION_CONTEXT()读取的值。

但是,所有这些都不能防止proc未能按确定的规避某人的意图运行。他们只是防止意外的误用。

答案 1 :(得分:0)

没有可靠的方法来执行此操作。选中@@ trancount只会为您提供信息,无论您是否正在进行交易,而且有人可以这样做:

BEGIN TRAN
EXECUTE nested_proc_directly

在这种情况下,proc中的事务计数b将大于0。正如其他人所说,您不能调用堆栈。所以,对不起。

答案 2 :(得分:0)

我在这里在两行之间进行了一点阅读,并猜测实际的问题是如何防止Procedure2以外的任何进程运行Procedure1

如果必须尽可能将其完全锁定,请创建一个专用的服务帐户来运行这些过程或其相关的工作,然后仅授予EXECUTE的{​​{1}}权限}到该专用帐户。

如果“完全锁定”足够好,请仅将Procedure2上的EXECUTE权限授予您已在生产中运行作业的服务帐户。至少这样可以防止流浪用户将它发射出去。

另一种想法是创建一个包含两个Procedure2的SSIS包,第一个包含Execute SQL Tasks中的所有代码,第二个包含Procedure1中的所有代码,然后删除proc并运行程序包。不过,我不关心将代码嵌入程序包中,因为维护很烦人。

答案 3 :(得分:0)

为此,您可以使用@@PROCID。唯一的问题是您需要通过输入传递参数。

 Traceback (most recent call last):
 File "test_code.py", line 66, in <module>
   testspark = spark.read.json(bucket_path + blob.name).cache()
 File "/home/anaconda3/envs/py37base/lib/python3.6/site-packages/pyspark/sql/readwriter.py", line 274, in json
return self._df(self._jreader.json(self._spark._sc._jvm.PythonUtils.toSeq(path)))
 File "/home/anaconda3/envs/py37base/lib/python3.6/site-packages/py4j/java_gateway.py", line 1257, in __call__
answer, self.gateway_client, self.target_id, self.name)
 File "/home/anaconda3/envs/py37base/lib/python3.6/site-packages/pyspark/sql/utils.py", line 63, in deco
return f(*a, **kw)
 File "/home/anaconda3/envs/py37base/lib/python3.6/site-packages/py4j/protocol.py", line 328, in get_return_value
format(target_id, ".", name), value)
py4j.protocol.Py4JJavaError: An error occurred while calling o51.json.
: java.io.IOException: No FileSystem for scheme: gs

输出

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