Максимальный уровень вложенности хранимой процедуры, функции, триггера или представления превышен в Visual Studio (ado.net), но не на сервере SQL. - PullRequest
3 голосов
/ 31 августа 2010

У меня проблема с рекурсивной функцией SQL.Первоначальная проблема в том, что у меня есть список сотрудников, у каждого из которых есть различные тренинги.Каждый из этих тренингов имеет некоторые предварительные требования.Например, чтобы иметь водительские права класса 1, у вас должен быть класс 5. Если я удаляю класс 5, мне нужно отключить класс 1.

Теперь, поскольку это дерево без фиксированной максимальной глубины (на самом делеЯ перестал проверять на 10ish) Я решил использовать рекурсию.Я написал две хранимые процедуры

[dbo].[spCheckTrainingPreqs]
@PIN int,
@training_id int,
@missingTraining int OUTPUT

и

[dbo].[spCheckTrainingPreqsEmployee] 
@PIN int

Теперь, когда я вызываю spCheckTrainingPreqsEmployee с номером сотрудника, он создает курсор для каждой комбинации pin / training_id и вызывает spCheckTrainingPreqs.spCheckTrainingPreqs использует рекурсивный локальный курсор для обхода дерева.

Теперь кикер.Он отлично работает в Visual Studio

DECLARE @return_value int

EXEC    @return_value = [dbo].[spCheckTrainingPreqsEmployee]
        @PIN = 12673

SELECT  'Return Value' = @return_value

GO

Но если я захожу в Visual Studio и добавляю его в адаптер таблицы как сохраненный процесс без возврата, я получаю сообщение об ошибке "Максимальное количество хранимых процедур, функций, триггеров илипревышен уровень вложенности представления (предел 32) "

Я проверил, что ни в одной из моих таблиц нет триггеров.Единственная сложность заключается в том, что многие таблицы имеют представления, основанные на них с подзапросами и даже с пользовательской функцией конкатенации с кодированием #.Помните, что запуск из диспетчера SQL работает нормально.

Полный код для справки

/****** Object:  StoredProcedure [dbo].[spCheckTrainingPreqs]    Script Date: 08/31/2010 10:13:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[spCheckTrainingPreqs]
@PIN int,
@training_id int,
@missingTraining int OUTPUT
AS
-- get the Prerequisites
declare @requiresID int
declare CurPrereqs cursor local for SELECT RequiresID FROM TrainingPrerequisites WHERE SourceID = @training_id
SET @missingTraining = 0
OPEN CurPrereqs
FETCH NEXT FROM CurPrereqs INTO @requiresID 
WHILE @@FETCH_STATUS = 0
BEGIN
    IF (@missingTraining = 0) -- stop when a missing training is found
    BEGIN
        IF (SELECT count(training_id) FROM employee_training WHERE PIN = @PIN AND training_id = @requiresID GROUP BY training_id) = 1
        BEGIN
            --they have the training 
            IF (@@NESTLEVEL  < 10) -- we only check 10 levels deep
            BEGIN
                EXEC spCheckTrainingPreqs @PIN, @requiresID, @missingTraining
                UPDATE employee_training SET missingPreReq = @missingTraining WHERE training_id = @training_id and PIN = @PIN;
            END
        END
        ELSE
        BEGIN
            SET @missingTraining = @requiresID
            UPDATE employee_training SET missingPreReq = @missingTraining WHERE training_id = @training_id and PIN = @PIN;
            CLOSE CurPrereqs
            DEALLOCATE CurPrereqs;
            RETURN 
        END

    END
FETCH NEXT FROM CurPrereqs INTO @requiresID 
END
CLOSE CurPrereqs
DEALLOCATE CurPrereqs;

и

/****** Object:  StoredProcedure [dbo].[spCheckTrainingPreqsEmployee]    Script Date: 08/31/2010 10:28:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Create date: 08/31/2010
-- Description: Checks all pre reqs for an employee
-- =============================================
ALTER PROCEDURE [dbo].[spCheckTrainingPreqsEmployee] 
    @PIN int
AS
BEGIN
    SET NOCOUNT ON;
    declare @training_id int
    declare @missingTraining int
    SET @missingTraining = 0
    declare CurPrereqsE cursor local for SELECT training_id FROM employee_training WHERE PIN = @PIN
    OPEN CurPrereqsE
    FETCH NEXT FROM CurPrereqsE INTO @training_id 
    WHILE @@FETCH_STATUS = 0
    BEGIN
        EXEC spCheckTrainingPreqs @PIN, @training_id, @missingTraining
    FETCH NEXT FROM CurPrereqsE INTO @training_id 
    END
    CLOSE CurPrereqsE
    DEALLOCATE CurPrereqsE;
END

1 Ответ

1 голос
/ 29 ноября 2011

Когда вы говорите:

Помните, что запуск из диспетчера SQL работает нормально

какие значения вы используете для проверки параметров? Ошибка в VS, вероятно, вызвана вызовом дизайнера. Стоит проверить, что вы вызываете процедуру с теми же параметрами, что и дизайнер.

Попробуйте использовать SQL Profiler для отслеживания вызовов SQL и проверки, какие именно значения передает VS. Затем вы можете выполнить точно такой же запрос из диспетчера SQL. Я предполагаю, что вы получите точно такой же результат.

...