Максимальная рекурсия 100 была исчерпана, прежде чем в SQL-запросе отобразилась ошибка завершения оператора.

Ошибка «Максимальная рекурсия 100 была исчерпана до завершения оператора», отображаемая в SQL-запросе

WITH DepartmentCTE AS
(   SELECT  ID, 
        DepartmentName, 
        RootID, 
        RecursionLevel = 1, 
        ParentRoot = CAST('None' AS NVARCHAR(max)),
        LastParentCatID = RootID,
        DisplayOrder
FROM    Department
UNION ALL
SELECT  cte.ID, 
        cte.DepartmentName,
        cte.RootID,
        cte.RecursionLevel + 1,
        ParentRoot = CASE WHEN cte.RecursionLevel = 1 THEN '' ELSE cte.ParentRoot + '>' END + c.DepartmentName,
        LastParentCatID = c.RootID,
        cte.DisplayOrder
FROM    DepartmentCTE cte
        INNER JOIN Department c
            ON c.ID = cte.RootID

), MaxRecursion AS
(   SELECT  ID, 
        DepartmentName, 
        RootID, 
        ParentRoot, 
        RowNum = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY RecursionLevel DESC),
        DisplayOrder
FROM    DepartmentCTE
)
SELECT  ID, DepartmentName, RootID, ParentRoot
FROM    MaxRecursion 
WHERE   RowNum = 1;

person Avinash Singh    schedule 07.10.2013    source источник


Ответы (2)


Вы можете ограничить количество уровней рекурсии, используя подсказку опции MAXRECURSION следующим образом: OPTION (MAXRECURSION 0); где значение (от 0 до 32767) указывает количество уровней рекурсии, 0 означает бесконечность.

Из документации для CTE:

Неправильно составленный рекурсивный CTE может вызвать бесконечный цикл. Например, если определение рекурсивного запроса к члену возвращает одинаковые значения как для родительского, так и для дочернего столбцов, создается бесконечный цикл. Чтобы предотвратить бесконечный цикл, вы можете ограничить количество уровней рекурсии, разрешенных для определенного оператора, используя подсказку MAXRECURSION и значение от 0 до 32 767 в предложении OPTION оператора INSERT, UPDATE, DELETE или SELECT. Это позволяет вам контролировать выполнение оператора до тех пор, пока вы не решите проблему с кодом, создающую цикл. Значение по умолчанию для всего сервера — 100. Если указано значение 0, ограничение не применяется. Для каждого оператора может быть указано только одно значение MAXRECURSION. Дополнительные сведения см. в разделе Подсказки по запросу (Transact-SQL).

А в документации по подсказкам запроса говорится:

MAXRECURSION число

Указывает максимальное количество рекурсий, разрешенных для этого запроса. Число — это неотрицательное целое число от 0 до 32767. Если указано значение 0, ограничение не применяется. Если этот параметр не указан, ограничение по умолчанию для сервера равно 100.

Когда во время выполнения запроса достигается заданное или заданное по умолчанию число для предела MAXRECURSION, запрос завершается и возвращается ошибка.

Из-за этой ошибки откатываются все эффекты оператора. Если оператор является оператором SELECT, могут быть возвращены частичные результаты или вообще не возвращаться результаты. Любые возвращаемые частичные результаты могут не включать все строки на уровнях рекурсии, превышающих указанный максимальный уровень рекурсии.

Чтобы использовать оператор, вы добавляете предложение OPTION после предложения FROM в запросе с использованием рекурсивного CTE.

Однако указание 0 может привести к плохим последствиям, если запрос переходит в бесконечный цикл.

person jpw    schedule 07.10.2013

Не уверен, что это то, что вы хотели, но понимаете, что CTE DepartmentCTE «вызывает» себя, потому что вторая часть его объединения — «From DepartmentCTE». Это очень полезное поведение, если задумано, и очень плохо, если не задумано. В вашем случае я не вижу ничего ограничивающего рекурсию. CTE будет называть себя бесконечно. Если вы используете рекурсию, обычно будет какое-то ограничивающее утверждение, такое как «Если уровень...» или «Если существует…). Уровень рекурсии 100 довольно щедрый для среды БД, и @jpw согласен с тем, что его отключение было бы плохим. В вашем случае действительно будет бесконечный цикл, пока процесс не рухнет или что-то в этом роде.

Было ли зацикливание вашим намерением? Если нет, удалите каким-либо образом DepartmentCTE. Если да, то найдите, как ограничить на основе один, когда вы «закончили». Если не уверены, возможно, дайте больше информации о цели, чтобы посмотреть, сможем ли мы понять.

person asantaballa    schedule 07.10.2013