为什么存储过程将返回0和选定的ID?

时间:2019-06-07 14:48:45

标签: sql tsql stored-procedures

我有一个这样的存储过程:

CREATE PROCEDURE [dbo].[create_myNewId]
    (@parentId BIGINT) 
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [Mapping] (ParentId)
    VALUES (@parentId)

    SELECT SCOPE_IDENTITY();
END

此函数单独运行时,将返回新的 id ,该新的 id 已分配给使用父ID 插入的新行。但是,当我做这样的事情时:

DECLARE @NewId int
EXEC @NewId = create_myNewId @parentId = 33333
SELECT @NewId

运行此命令时,输出窗口将显示存储过程的结果,该结果返回一个ID,但@NewId始终为0。我通过将存储过程更改为使用RETURN SCOPE_IDENTITY()来解决了这个问题,但是想知道为什么SELECT在这种情况下不起作用?

我怀疑它是0周围的东西,它是首先从存储过程而不是结果中返回成功状态,但是很好奇为什么直接从客户端调用时却不发生这种情况。

3 个答案:

答案 0 :(得分:1)

不!正确编写程序:

CREATE PROCEDURE [dbo].[create_myNewId] (
    @parentId bigint,
    @outId bigint OUTPUT
) AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @ids TABLE (id bigint);

    INSERT INTO [Mapping](ParentId)
        OUTPUT id INTO @ids
        VALUES (@parentId);

    SELECT @outId = id
    FROM @ids;
END;

然后将其称为:

DECLARE @NewId int;
EXEC create_myNewId @parentId = 33333, @NewId OUTPUT;
SELECT @NewId;

OUTPUT子句是从数据修改子句获取结果的推荐方法。使用*_IDENTITY()函数的旧方法应该被淘汰。

存储过程确实返回值。这些是 integers ,旨在返回状态信息。其他信息应通过OUTPUT参数返回。

答案 1 :(得分:0)

Microsoft对存储过程的设计意图是,它们总是返回一个int来描述该过程执行的过程的成功程度。它并非旨在返回结果数据,您可以自由定义要返回的用于描述成功,部分成功等的位。如果需要,可以滥用它来返回整数结果数据(例如,计数查询),但这不是设计意图

在存储过程中执行选择查询会创建一个结果集,如果该存储过程是旨在返回数据的那种类型,则可以在客户端上读取该结果集

答案 2 :(得分:0)

我的建议是使用OUTPUT参数。不仅在调用SPROC时更“容易”使用,而且对于调用SPROC的人也更加清晰。

    CREATE PROCEDURE [dbo].[create_myNewId] (
        @parentId BIGINT,
        @myNewId  BIGINT OUTPUT)
    AS
    BEGIN
        SET NOCOUNT ON;

        INSERT INTO [Mapping] ([ParentId])
        VALUES (@parentId);

        SET @myNewId = SCOPE_IDENTITY();
    END;
    GO

然后您将像这样呼叫您的SPROC:

    DECLARE @myNewId BIGINT;

    EXECUTE [dbo].[create_myNewId] @parentId = 0,               -- bigint
                                   @myNewId = @myNewId OUTPUT;  -- bigint

    SELECT  [This was just inserted] = @myNewId;