Превышение уровня вложенности вызовов SQL Server SP 32 - PullRequest
1 голос
/ 28 февраля 2011

Я столкнулся с бизнес-случаем, когда мне нужны вложенные вызовы SP, превышающие уровень 32, что является пределом для SQL Server.Кто-нибудь может сказать, есть ли возможность увеличить этот лимит?

Ответы [ 3 ]

4 голосов
/ 28 февраля 2011

Нет, 32 - это предел: Спецификации максимальной емкости для SQL Server

Вложенные хранимые процедуры

32 - глубокий стек вызовов;Я никогда не достигал этого предела раньше.Он предлагает вам искать альтернативный подход.

1 голос
/ 28 февраля 2011

Если вы достигнете этого предела, то вы должны использовать udfs или CTE для своего рекурсивного кода.Если это не рекурсивно, это действительно плохой дизайн.

У меня никогда не было глубины более 4, включая триггер

0 голосов
/ 24 июня 2013

Рекурсивный вызов МОЖЕТ быть очень полезной функцией, особенно когда вы выводите XML, и вам нужно получить дочерние узлы XML, которые имеют равный по формату родительский узел. Обходной путь - использование хранимых процедур для обработки родительских / дочерних отношений с недостатком более сложного / избыточного кода. Скажем, у вас есть:

create table Users (UserID int, Name nvarchar(50), ManagerID int null)
insert into Users (1, 'Carl', null)
insert into Users (2, 'Tom', 1)
insert into Users (3, 'John', 1)

и

create function GetUser(@UserID int)
returns XML as
begin
    declare @xml XML
    SET @xml = (
        SELECT [UserID] "User/@UserID"
            , [Name] "User/@Name"
            FROM Users
            WHERE [UserID] = @UserID
        FOR XML PATH(''), TYPE
    )
    return @xml
end

Чтобы получить все менеджеры в XML:

create proc GetAllManagers() as
begin
    set nocount on;
    SELECT dbo.GetUser([UserID]) 
    FROM Users 
    WHERE [ManagerID] IS NULL
    FOR XML PATH(''), TYPE, root('Managers')
end

Теперь к проблеме. Что если для каждого менеджера я хочу, чтобы все пользователи принадлежали менеджеру? Я хотел бы, чтобы моя функция могла вызывать сама себя:

alter function GetUser(@UserID int, @IsIncludeChildren bit)
returns XML as
begin
    declare @xml XML
    SET @xml = (
        SELECT [UserID] "User/@UserID"
            , [Name] "User/@Name"
            , (SELECT dbo.GetUser([UserID], 0)) "User/Children"
            FROM Users
            WHERE [ManagerID] = @UserID AND @IsIncludeChildren = 1
        FOR XML PATH(''), TYPE
    )
    return @xml
end

и называя это просто

alter proc GetAllManagers() as
begin
    set nocount on;
    SELECT dbo.GetUser([UserID], 1) 
    FROM Users 
    WHERE [ManagerID] IS NULL
    FOR XML PATH(''), TYPE, root('Managers')
end

Но это невозможно из-за лимита вложенности. Итак, обходной путь (с использованием первой функции):

alter proc GetAllManagers() as
begin
    set nocount on;
    SELECT 
      dbo.GetUser([UserID]) 
    , (
      SELECT dbo.GetUser([UserID])
          FROM Users 
          WHERE [ManagerID] = [Users].[UserID]
          FOR XML PATH(''), TYPE
    ) "User/Children"

    FROM Users as [Users]
    WHERE [ManagerID] IS NULL
    FOR XML PATH(''), TYPE, root('Managers')
end

Это не так уж плохо, но если у вас есть множество других процедур, возвращающих пользовательские данные, вам придется строить отношения родитель / потомок во всех процессах, а не в одной функции!

Итак, Microsoft, исправь это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...