3


0

SQL ServerではなくVisual Studio(ado.net)でストアドプロシージャ、関数、トリガー、またはビューのネストレベルの最大値を超えました

再帰的なSQL関数に問題があります。 元の問題は、従業員のリストがあり、各従業員がさまざまなトレーニングを受けていることです。 これらの各トレーニングには、いくつかの前提条件があります。 たとえば、クラス1のドライバーライセンスを取得するには、クラス5が必要です。 クラス5を削除する場合、クラス1を無効にすることを確認する必要があります。

これは固定された最大深度のないツリーなので(実際には10ishでチェックを停止します)、再帰を使用することにしました。 2つのストアドプロシージャを作成しました

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

and

[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)」というエラーが表示されます。

テーブルにトリガーがないことを確認しました。 唯一の複雑さは、テーブルの多くがサブクエリやc#コード化されたカスタム連結関数を使用したビューに基づいていることです。 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;

and

/****** 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 Answer


1


あなたが言う時:

_ SQLマネージャーから実行すると問題なく動作することを忘れない _

テストするパラメーターにどの値を使用していますか? VSのエラーは、おそらくデザイナーによる呼び出しが原因です。 デザイナーが使用しているのと同じパラメーターを使用してプロシージャを呼び出していることを確認する価値があります。

SQLプロファイラーを使用してSQL呼び出しをトレースし、VSが渡す値を正確に確認してください。 その後、SQLマネージャー内からまったく同じクエリを実行できます。 私の推測では、まったく同じ結果が得られるでしょう。