SQL 命令调用递归存储过程

Posted

技术标签:

【中文标题】SQL 命令调用递归存储过程【英文标题】:SQL command calls recursive stored procedure 【发布时间】:2021-04-13 21:10:41 【问题描述】:

我在 SQL Server 中有一个存储过程,我使用 SqlConnectionSqlCommand 从 ASP.NET Core 应用程序调用它。我不断收到异常:

超过最大存储过程、函数触发器或视图嵌套级别(限制 32)

我不知道这是什么意思,所以我查了一下并看到了类似的帖子,但我所能收集到的只是我很可能在我的存储过程中发生了某种递归。在这个存储过程中,只有一条 INSERT 语句被执行 32 次而不是只执行一次。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[addToTable]
    (@title nvarchar(100), @genre int)
AS 
BEGIN
    INSERT INTO [dbo].[Books] (Title, GenreId)
    VALUES (@title, @genre)
END

BEGIN
    EXEC addToTable @title, @genre
END

C# 调用非常简单。

using (SqlConnection con = new SqlConnection("Connection String"))

    using (SqlCommand cmd = new SqlCommand("dbo.addToTable", con))
    
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@title", SqlDbType.NVarChar).Value = "string value";
        cmd.Parameters.Add("@genre", SqlDbType.NVarChar).Value = 5;

        cmd.Connection.Open();
        cmd.ExecuteNonQuery();  //Exception happens here
        cmd.Connection.Close();
    

我设置了一个断点并单步执行代码,异常发生在ExecuteNonQuery(),我只能假设这是因为程序中的某些问题。

【问题讨论】:

最后不应该有那个 EXEC 命令。删除它。 存储过程是整批。所以你必须在它和执行过程之间加上GO,把它分成第二批。 【参考方案1】:

最后不应该有那个 EXEC 命令。删除它。这里发生的是您声明一个存储过程,然后在定义中执行它。所以基本上每次调用存储过程时,它都会调用自己。

就这样做

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[addToTable]
    (@title nvarchar(100), @genre int)
AS 
BEGIN
    INSERT INTO [dbo].[Books] (Title, GenreId)
    VALUES (@title, @genre)
END

--Delete the following
--BEGIN
--EXEC addToTable @title, @genre
--END

【讨论】:

我担心的是,如果其他人在数据库上创建了存储过程,并且他们添加了一个 exec 语句怎么办?有办法避免吗? 没有。使用 C# 代码无法避免部分存储过程。您必须修改存储过程本身。

以上是关于SQL 命令调用递归存储过程的主要内容,如果未能解决你的问题,请参考以下文章

sybase存储过程中怎么调用存储过程

在 phpmyadmin 中从 mysql 命令行调用 mysql 存储过程

oracle数据库调用存储过程

SQL,While循环,递归存储过程或游标中哪个更快?

Oracle 存储过程

Oracle SQL 存储过程调用与执行