Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 存储过程在被另一个存储过程调用时未返回正确的值_Sql_Sql Server - Fatal编程技术网

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

Sql 存储过程在被另一个存储过程调用时未返回正确的值,sql,sql-server,Sql,Sql Server,我在另一个存储过程中执行存储过程时遇到问题。基本上,当我自己执行存储过程时,它工作正常,插入并返回正确的值。但是,当我在另一个存储过程中调用同一个存储过程时,使用与手动尝试时相同的输入,它不会插入任何内容,也不会返回正确的值。变量的处理方式有什么奇怪的地方吗?还是其他什么地方出了问题?请参阅下面的代码 第一个程序: ALTER PROCEDURE [dbo].[createOrgLevel] @name varchar(255), @level int, @parenti

我在另一个存储过程中执行存储过程时遇到问题。基本上,当我自己执行存储过程时,它工作正常,插入并返回正确的值。但是,当我在另一个存储过程中调用同一个存储过程时,使用与手动尝试时相同的输入,它不会插入任何内容,也不会返回正确的值。变量的处理方式有什么奇怪的地方吗?还是其他什么地方出了问题?请参阅下面的代码

第一个程序:

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,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
同样,如果我手动执行第一个过程,它会正确插入组织级别并返回ID。但是,当在第二个过程中调用它时,它不会插入任何新的组织级别,只会返回第一个组织级别的ID,它会找到我手动插入的所有组织的父级


我尝试过解决这个问题,在第二秒内执行该过程之前打印出所有参数,它们与我手动尝试时完全相同。我还检查了错误是否发生在哪里,它正在输入catch语句,但没有。有人能帮我吗?

是的,这是因为您在每次迭代中重构@newid变量,并且在每次连续运行时,上一次运行的值仍然存储在其中

你的问题实际上是:

   SELECT @newid = [id] from dbo.[Org 3]
        WHERE
        [Name] = @name and
        [Parent ID] = @parentid
@newidalready有一个值,由于查询不返回任何内容,所以该值不会被NULL覆盖,而是保留上次的值

您应该做的是:

在内部存储过程的开头将@newid设置为NULL 或 使用不同的变量名称检查组织是否存在,然后返回到输出的组织在SP或 您可以重写SELECT,以设置在不返回任何内容的情况下将用NULL覆盖的值

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

是的,这是因为您在每次迭代中重构@newid变量,并且在每次连续运行时,上一次运行的值仍然存储在其中

你的问题实际上是:

   SELECT @newid = [id] from dbo.[Org 3]
        WHERE
        [Name] = @name and
        [Parent ID] = @parentid
@newidalready有一个值,由于查询不返回任何内容,所以该值不会被NULL覆盖,而是保留上次的值

您应该做的是:

在内部存储过程的开头将@newid设置为NULL 或 使用不同的变量名称检查组织是否存在,然后返回到输出的组织在SP或 您可以重写SELECT,以设置在不返回任何内容的情况下将用NULL覆盖的值

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

如果注释掉createOrgLevel并打印输出以查看其是否迭代,会发生什么情况?您可能希望使用范围\标识而不是@标识@@identity将返回上次插入的会话标识。scope_identity将返回上次插入的作用域标识。我注意到,在调用过程中,字符串值是nvarchar,而在被调用过程中,字符串值是varchar。我不确定这是导致问题的原因,但值得快速测试。如果注释掉createOrgLevel并打印输出以查看其是否迭代,会发生什么情况?您可能希望使用范围\标识而不是@标识@@identity将返回上次插入的会话标识。scope_identity将返回上次插入的作用域标识。我注意到,在调用过程中,字符串值是nvarchar,而在被调用过程中,字符串值是varchar。我不确定这是导致问题的原因,但值得一试。谢谢!我想我确保了我没有重复使用变量名,但我想我已经盯着这个太久了,以至于我真的错过了它。将其设置为null非常有效!谢谢我想我确保了我没有重复使用变量名,但我想我已经盯着这个太久了,以至于我真的错过了它。将其设置为null非常有效!