简体   繁体   English

当被另一个存储过程调用时,存储过程未返回正确的值

[英]Stored procedure not returning correct value when called by another stored procedure

I'm having issues executing a stored procedure within another stored procedure. 我在另一个存储过程中执行存储过程时遇到问题。 Basically, when I execute my stored procedure by itself, it works just fine, and inserts and returns the correct values. 基本上,当我自己执行存储过程时,它可以正常工作,并插入并返回正确的值。 However, when I call the same stored procedure within another stored procedure, with the same input as when I tried it manually, it doesn't insert anything, and doesn't return the correct value. 但是,当我在另一个存储过程中调用相同的存储过程时,使用与手动尝试时相同的输入,它不会插入任何内容,也不会返回正确的值。 Is there something weird going on with how the variables are handled? 处理变量的方式是否有些奇怪? Or is something else going wrong? 还是出了什么问题? See my code below. 请参阅下面的代码。

The first procedure: 第一个过程:

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

An abbreviated version of the procedure calling it: 该过程的缩写形式:

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,dbo.@level3),
    (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

Again, if I manually execute the first procedure, it correctly inserts the Org Level, and returns the ID. 同样,如果我手动执行第一个过程,它将正确插入组织级别,并返回ID。 However, when it is called in the second procedure, it doesn't insert any new Org Levels, and just returns the ID of the first Org Level it finds (the parent level for all Orgs, that I manually inserted). 但是,在第二个过程中调用它时,它不会插入任何新的组织级别,而只是返回找到的第一个组织级别的ID(我手动插入的所有组织的父级别)。

I have tried troubleshooting this issue, by printing out all the parameters before the procedure is executed within the second, and they are exactly the same as when I try it manually. 我已尝试解决此问题,方法是在第二步执行该过程之前先打印出所有参数,这些参数与我手动尝试时的参数完全相同。 I also checked to see if errors where occurring, and it was entering the catch statement, but it wasn't. 我还检查了是否发生了错误,是否正在输入catch语句,但是没有。 Can anyone help me out here? 有人可以帮我从这里出去吗?

Yes, this is because you refactor @newid variable in each iteration and it's value from last run is still stored in it on each consecutive run. 是的,这是因为您在每次迭代中都重构了@newid变量,并且上一次运行的值仍在每次连续运行时存储在其中。

Your problem is here actually: 您的问题实际上在这里:

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

@newid already has a value, and since the query does not return anything, value is not overrided with NULL but remains from last time. @newid已经有一个值,并且由于查询不返回任何内容,因此该值不会被NULL覆盖,而是从上次开始保留。

What you should do is either: 您应该做的是:

  • Set @newid to NULL at the start of your inner stored procedure or 在内部存储过程开始时将@newid设置为NULL或
  • Use different name for variable to check if org exists then the one you are returning to output (set the return value at the end of SP) or 对变量使用不同的名称来检查org是否存在,然后再返回输出(在SP的末尾设置返回值)
  • You can rewrite SELECT to SET which would overwrite value with NULL if nothing is returned 您可以将SELECT重写为SET ,如果什么都没有返回,它将用NULL覆盖值

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM