2017-07-03 19 views
0

別のストアドプロシージャ内でストアドプロシージャを実行する際に問題が発生しています。基本的には、自分でストアドプロシージャを実行すると、正常に動作し、正しい値が挿入されて返されます。しかし、別のストアドプロシージャ内で同じストアドプロシージャを呼び出すと、手動で試したときと同じ入力で、何も挿入されず、正しい値が返されません。どのように変数が処理されるかと何か変わっていますか?それとも何か他にうまくいかないのですか?以下の私のコードを見てください。他のストアドプロシージャによって呼び出されたときに正しい値を返さないストアドプロシージャ

最初の手順:

ALTER PROCEDURE [dbo].[createOrgLevel] 
    @name varchar(255), 
    @level int, 
    @parentid bigint, 
    @newid bigint OUTPUT 
AS 
    SET NOCOUNT ON; 
    -- Check to see if it exists 
    SELECT @newid = [id] from dbo.[Org 3] 
     WHERE 
     [Name] = @name and 
     [Parent ID] = @parentid 
     IF @newid IS NULL 
     -- If it doesn't exist, insert 
      BEGIN 
       INSERT INTO [dbo].[Org 3] 
        ([Parent ID] 
        ,[Name] 
        ,[Level]) 
       VALUES 
        (@parentid 
        ,@name 
        ,@level) 
       SET @newid = @@identity 
      END 
END 

手続きの簡略版はそれを呼び出す:

ALTER PROCEDURE [dbo].[createOrg] 
    @level1 nvarchar(255), 
    @level2 nvarchar(255), 
    @level3 nvarchar(255), 
    @level4 nvarchar(255), 
    @level5 nvarchar(255), 
    @level6 nvarchar(255), 
    @level7 nvarchar(255), 
    @level8 nvarchar(255), 
    @orgid bigint OUTPUT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE 
    @parid bigint, 
    @curname nvarchar(255) 
    DECLARE 
    @levels table (num int, name nvarchar(255)) 
    INSERT @levels(num, name) values (1,@level1),(2,@level2),(3,[email protected]), 
    (4,@level4),(5,@level5),(6,@level6),(7,@level7), 
    (8,@level8) 

    BEGIN 
     BEGIN TRY 
      SET @curname = @level1 
      EXEC dbo.createOrgLevel @name = @curname, @level = 1, @parentid = 0, @newid = @orgid OUTPUT 
      SET @parid = @orgid 
     END TRY 
     BEGIN CATCH 
      SET @orgid = NULL 
      RETURN -1 
     END CATCH 

     DECLARE @cnt INT = 2; 

     WHILE @cnt < 9 
     BEGIN 
      BEGIN TRY 
       SELECT @curname = name FROM @levels WHERE num = @cnt 
    ----------------------------------- 
    -- This is where it is executed, and not inserting/returning the correct value. It keeps 
    -- returning the value from the previous 'loop', and not inserting anything. It's not 
    -- entering the Catch, though. 

       EXEC dbo.createOrgLevel @name = @curname, @level = @cnt, @parentid = @parid, @newid = @orgid OUTPUT 

    ----------------------------------- 
       SET @parid = @orgid 
      END TRY 
      BEGIN CATCH 
       RETURN 1 
      END CATCH 
      SET @cnt = @cnt + 1 
     END 
    END 
END 

を繰り返しますが、私は手動で最初の手順を実行している場合、それは正しく組織レベルの挿入、およびリターンID。しかし、2番目のプロシージャで呼び出されると、新しいOrgレベルは挿入されず、見つかった最初のOrgレベル(手動で挿入したすべてのOrgの親レベル)のIDが返されます。

手続きを2番目の時間内に実行する前に、すべてのパラメータをプリントアウトすることでこの問題のトラブルシューティングを試みましたが、手動で試したときとまったく同じです。私はまた、どこにエラーが発生したのか、それがcatchステートメントに入っているのかを確認しましたが、そうではありませんでした。誰でもここで私を助けることができますか?

+0

createOrgLevelをコメントアウトして出力を印刷して反復するかどうかはどうなりますか? –

+0

@@ indentityの代わりにscope_identityを使用したいと思うでしょう。 @@ identityはセッションの最後に挿入されたアイデンティティを返します。 scope_identityはスコープの最後に挿入されたアイデンティティを返します。 – Peter

+1

私は呼び出した手続きで文字列の値が 'nvarchar'であるのに対し、呼び出された手続きでは文字列の値が' varchar'であることに気付きました。それが問題の原因になっているのかどうかはわかりませんが、簡単なテストの価値があります。 –

答えて

3

はい、これは、各反復で変数@newidをリファクタリングし、最後の実行からの値が各連続実行でそれに格納されているためです。

あなたの問題は、実際にはここにある:

SELECT @newid = [id] from dbo.[Org 3] 
     WHERE 
     [Name] = @name and 
     [Parent ID] = @parentid 

@newidはすでに値を持っており、クエリが何も返さないため、値はNULLでオーバーライドされていませんが、最後の時から残っています。

あなたは何をすべきいずれかです:ORGは、あなたが戻ってきているものを存在するかどうかを確認するためにあなたの内側のストアドプロシージャ または変数の

  • 利用別の名前の先頭にNULLに

    • セット@newid出力にあなたは何も返されなかった場合はNULLで値を上書きすることになるSETSELECTを書き換えることができますか
    • (SPの末尾に戻り値を設定)

      SET @newid = (SELECT id FROM dbo.[Org 3]..) 
      
  • +0

    ありがとう!私は変数名を再使用していないことを確認したと思っていましたが、私はこれをあまりにも長く見つめていました。これをnullに設定すると、魅力的に機能しました! –

    関連する問題