2017-07-03 62 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就像魅力一样工作! –

相关问题