2017-07-03 114 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。但是,當它在第二個過程中被調用時,它不會插入任何新的組織級別,並且只返回它找到的第一個組織級別的ID(所有組織的父級別,我手動插入)。

我曾嘗試解決此問題,通過前一秒中執行的程序打印出所有的參數,它們是完全一樣的,當我嘗試手動的。我也檢查了是否發生了錯誤,並且它正在進入catch語句,但事實並非如此。有人可以幫我從這裏出去嗎?

+0

如果註釋掉createOrgLevel並打印輸出以查看它是否迭代會發生什麼? –

+0

你可能想使用scope_identity而不是@@ indentity。 @@身份將返回會話的最後插入的身份。 scope_identity將返回該作用域的最後插入的標識。 – Peter

+1

我注意到,在調用過程中,字符串值是'nvarchar',而在調用過程中,字符串值是'varchar'。我不確定那是什麼原因導致了這個問題,但值得快速測試。 –

回答

3

是的,這是因爲你重構在每個迭代@newid變量,這是從去年運行值仍保存在其上的每個連續運行。

你的問題是在這裏實際上是:

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

@newid已經有一個值,因爲查詢不返回任何東西,值不與NULL overrided但是從最後一次保持。

你應該做的是兩種:

  • 設置@newid爲NULL在你內心的存儲過程 或
  • 使用變量不同名稱的開頭,以檢查是否組織存在,那麼你正在返回一個輸出或
  • (在SP年底設定的返回值),可以重寫SELECTSET這將覆蓋與NULL值,如果不返回任何

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

謝謝!我以爲我確定我沒有重複使用變量名稱,但是我想我長久以來一直盯着它,以至於我實際上錯過了它。將它設置爲null就像魅力一樣工作! –

相關問題