【问题标题】:Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)超出最大存储过程、函数、触发器或视图嵌套级别(限制 32)
【发布时间】:2013-08-22 11:59:10
【问题描述】:

我正在创建一个存储过程,但在执行该过程时出现了特定错误。

消息 217,级别 16,状态 1,过程 SendMail_Renewapp,第 77 行 超出最大存储过程、函数、触发器或视图嵌套级别(限制为 32)。

谁能帮我解决这个问题。

我的程序如下..

`ALTER PROCEDURE [dbo].[SendMail_Renewapp] 
-- Add the parameters for the stored procedure here

AS
BEGIN
declare @xml nvarchar(max)
declare @body nvarchar(max)
declare @currentdate datetime;
declare @ExpDate datetime;
declare @mailsendingdate datetime;
declare @renewtime varchar(10);
    DECLARE @AgencyId int;
DECLARE @ApplicationID int;
declare @emailid varchar(100);

set @currentdate=getdate();


                --Fetching the application details: start--
                DECLARE AppCursor CURSOR FOR 
                Select top 5 applications.ap_id,applications.ap_expiry_date,agency.ag_co_email from applications  join agency on applications.ap_agency_id=agency.ag_id
                 where ap_status='AS' and ap_iame_flag='IA' and ap_expiry_date != '' 
                    OPEN AppCursor
                    FETCH NEXT FROM AppCursor INTO @ApplicationID,@ExpDate,@emailid

                    WHILE @@FETCH_STATUS = 0 
                    BEGIN

                     SET @renewtime = ABS(DATEDIFF(day, @currentdate, @ExpDate))
                            if(@renewtime=180)

                                BEGIN

                                    --SET @xml = CAST(( SELECT [ag_id] AS 'td','',[ag_name] AS 'td','',[ag_co_email] AS 'td','',[ag_mobile] AS 'td'FROM  beesl.dbo.Agency where @renewtime < 180
--FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))

SET @body ='<html>
<body>
   <div>
<div>
<H3>Agencies Details whose payment are still pending for last 3 months</H3>
</div>
<table cellpadding="4" cellspacing="1" bgcolor=#FFFFFF   border=1 rules=none frame=box  > 
<tr  >
<th style=border:1px solid #000000;  align=left bgcolor=#c2c2c2> Agency ID </th>
 <th style=border:1px solid #000000;  align=left bgcolor=#c2c2c2> Agency Name </th> 
<th style=border:1px solid #000000;   align=left bgcolor=#c2c2c2> Agency Email </th> 
<th style=border:1px solid #000000;   align=left bgcolor=#c2c2c2> Contact Number </th> 

</tr>'   
    SET @body = @body + @xml +'</table></div></body></html>'

EXEC msdb.dbo.sp_send_dbmail 
@profile_name='BEE', 
@recipients='emailid@emailid.com', 
@subject='Renew Applications',
--@file_attachments = 'D:\beelogo.png',
@importance= High,
--@body = 'Testing'
@body = @body,
@body_format ='HTML';

                                END


                    FETCH NEXT FROM AppCursor INTO      @ApplicationID,@ExpDate,@emailid
                END
                    CLOSE AppCursor
                    DEALLOCATE AppCursor
                --Fetching the application details: end--


  END`

【问题讨论】:

标签: sql-server tsql stored-procedures


【解决方案1】:

使用 “去” 之后 结尾 声明

【讨论】:

  • 请解释你的答案。
  • SO 有很多 END 语句(我也是),但我应该把 GO 放在哪里?在最底部(也就是最后一个 END 语句)还是在我在 IF 语句中调用的每个 SP 中?
  • 是的,这行得通——但我完全惊呆了。谢谢
【解决方案2】:

该过程是用它自己的 EXEC 创建的。因此,必须在 EXEC 之前放置一个 GO,以便在执行之前创建/更改该过程。因此,避免了递归。

【讨论】:

  • 我忘记在我的存储过程中注释掉我的“测试”EXEC。这正是我的问题,谢谢!
【解决方案3】:

使用TRIGGER_NESTLEVEL函数在触发器的开头检查触发器嵌套级别,如果触发器级别大于1,则停止触发器执行操作。

 IF TRIGGER_NESTLEVEL() > 1
     RETURN

由于嵌套级别超过其限制而发生错误,因为我们都知道触发器不断触发并且难以控制触发器的行为。 TRIGGER_NESTLEVEL 函数返回嵌套层级,我们可以停止嵌套层级增加。

【讨论】:

    【解决方案4】:

    删除BEGINENDIF 语句

    例子

    WHILE @@FETCH_STATUS = 0
    BEGIN
    
        IF @variable
        --NO BEGIN
           --Do this
        --NO END
    END
    

    【讨论】:

    • 这对我有用。非常感谢!!你能告诉我“BEGIN END”有什么不同吗?
    • 说实话没有。我通常会使用 BEGIN - END 来包装任何逻辑块,类似于 c#“{}”中的花括号。我找到了this question,我认为它回答了这个问题
    【解决方案5】:

    使用

    RETURN
    

    在程序结束时

    【讨论】:

      【解决方案6】:

      好的,所以这个已经很老了,所以我想我会提供正确的答案。您应该在存储过程的顶部添加 SET NOCOUNT ON 并在尝试返回结果(您的最终选择)之前添加 SET NOCOUNT OFF。

      如果没有这个语句,你的执行会将每一个 select 语句都当作结果输出。当外部 ADO 或 ADO.NET 尝试调用存储过程并获取结果时,您将收到“超出最大存储过程、函数、触发器或视图嵌套级别(限制 32)”消息。是你的光标的 select 语句把事情搞砸了。

      参考:https://docs.microsoft.com/en-us/sql/t-sql/statements/set-nocount-transact-sql?view=sql-server-ver15

      【讨论】:

        【解决方案7】:

        RECURSIVE_TRIGGERS 更改您的数据库。

        如果允许嵌套触发器并且链中的触发器启动无限循环,则超出嵌套级别并且触发器终止。那个时候你确实得到了这个错误。所以只需运行这个查询。

        USE yourdatabase 
         GO
            -- Turn recursive triggers OFF in the database. 
              ALTER DATABASE yourdatabase    
              SET RECURSIVE_TRIGGERS OFF 
        GO
        

        希望您的问题能够得到解决。

        【讨论】:

        • 这不是一个很好的解决方案。首先,这是生产环境的巨大变化。其次,你是在回避问题,而不是找到根本问题并加以解决。
        【解决方案8】:

        我的问题是存储过程,不是触发器,也没有游标。过程中的EXEC 命令是其他答案指出的原因。但是我不能在 SSMS v18.5 的EXEC 命令之前的任何地方添加GO。它给了我一个错误。原来嵌套在里面的过程有它自己的 TRY/CATCH 块。在该过程结束时添加GO 并不能解决问题。我必须删除那里的 TRY/CATCH 块才能使其正常工作。不确定这只是我个人还是对其他人有帮助。

        【讨论】:

          【解决方案9】:

          就我而言,问题在于 UPDATE 有 2(两个)存储过程。所以,试着只做一个存储过程。谢谢!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-06
            • 2022-07-20
            • 1970-01-01
            • 2014-04-10
            • 2016-10-14
            • 2016-08-03
            相关资源
            最近更新 更多