【问题标题】:Returning a value in OUTPUT parameter in a sproc在存储过程中的 OUTPUT 参数中返回一个值
【发布时间】:2011-06-15 01:09:55
【问题描述】:

我有一个返回对象所有字段的存储过程。

CREATE PROCEDURE getCustomer
(
   @CustomerId int OUTPUT
)
AS
BEGIN
    SELECT @CustomerId=CustomerId,FirstName,LastName FROM Customers
END

我希望能够将对象的 id 作为输出参数返回,以便另一个 sproc 可以使用它。我在这个例子中得到这个错误:

A SELECT statement that assigns a value to a variable must not be combined with 
data-retrieval operations.

CREATE PROCEDURE getCustomer_and_more
AS
BEGIN
DECLARE @CustomerId int

EXEC getCustomer @CustomerId OUTPUT

-- call another sproc that requires this @CustomerId
END

【问题讨论】:

    标签: sql sql-server tsql sql-server-2008 stored-procedures


    【解决方案1】:

    当您的SELECT 语句分配变量值时,SELECT 中的所有字段都必须分配给一个局部变量。

    将您的 SPROC 更改为

    CREATE PROCEDURE getCustomer
    (
     @CustomerId int OUTPUT
    )
    AS
    BEGIN
        DECLARE @FirstName VARCHAR(50)
        DECLARE @LastName VARCHAR(50)
    
        SELECT @CustomerId=CustomerId, @FirstName = FirstName, @LastName =LastName 
        FROM Customers
    

    您不必使用它们变量,但必须以这种方式分配它们。

    您的 BETTER 选项是删除这些字段。如果不需要它们,请不要费心选择它们。

    [编辑]回复您的评论

    因此,您可以通过拆分变量的分配并选择其他字段来执行您想做的事情,如下所示:

    CREATE PROCEDURE getCustomer
    (
     @CustomerId int OUTPUT
    )
    AS
    BEGIN
    
        SELECT @CustomerId=CustomerId FROM Customers
    
        SELECT FirstName, LastName, {A_BUNCH_OF_OTHER_FIELDS}
        FROM
            Customers
    

    这将允许您获取输出参数并选择所有其他数据,而无需为每个字段定义参数。您必须权衡易用性(不必定义很多本地变量)与性能(必须运行两条语句而不是一条语句)。然而,这对我来说似乎有点奇怪。

    我不太清楚您是否需要 getCustomer_and_more 中可用的 GetCustomer 存储过程中的其他值。如果你这样做了,那么是的,你必须为你需要的每个值定义 OUTPUT 参数

    【讨论】:

    • 我需要所有的字段,其中有很多,因为我需要在业务层构造一个对象。所以你是说为每个字段声明变量是唯一的方法?
    • 我为您提供了一个可能的解决方案,但是当我尝试编辑帖子时,SO 出现了问题。一旦我可以回复,我会在我的主要回复中发布。
    【解决方案2】:

    查询中有错误:FirstNameLastName 是多余的。

    SELECT @CustomerId = CustomerId
    FROM Customers
    

    此外,我假设您在“客户”表中有多个客户。所以这个查询将返回最后一个 CustomerId,我认为这不是你想要的。所以你需要添加WHERE条件,或者TOP 1

    类似这样的:

    CREATE PROCEDURE getCustomer  (@CustomerId int OUTPUT)
    AS
    BEGIN
        select @CustomerId = id
        from Customer
        where <SomeCondition>
    END
    

    [编辑] 正如您所说的那样,SELECT 语句中没有错误,它可以编译并正常工作,这是证明。请尝试此代码不会出现问题。

    CREATE PROCEDURE getCustomer
    (
       @CustomerId int OUTPUT,
       @CustomerName varchar(10) OUTPUT
    )
    AS
    BEGIN
        SELECT @CustomerId = 666, @CustomerName = 'Test'
    END
    GO
    
    CREATE PROCEDURE getCustomer_and_more
    AS
    BEGIN
        DECLARE @CustomerId int
        DECLARE @CustomerName varchar(10)
    
        EXEC getCustomer @CustomerId OUTPUT, @CustomerName OUTPUT
    
        SELECT @CustomerId, @CustomerName
    END
    GO
    
    EXEC getCustomer_and_more
    

    这是导致您的错误的代码:

    DECLARE @CustomerId int
    
    SELECT @CustomerId = CustomerId, FirstName, LastName
    FROM Customers
    

    这不是合法的SELECT 声明。试试这段代码,你会看到与问题中显示的完全相同的错误。

    【讨论】:

    • 查询没有错误,需要所有字段在业务层构造对象。另外,我需要从另一个 sproc 调用这个 sproc 并在其中只使用 CustomerId。有一个WHERE 子句保证返回0 或1 条记录。这没有回答我原来的问题。
    • @kateroh 您看到的错误是因为您的第一个过程中的SELECT。第二个过程是正确的。您遇到的问题与输出参数本身无关。
    • @kateroh - 在我的答案中添加了一个查询来证明您的错误。
    • "所以这个查询将返回最后一个 CustomerId" - 没有根据的假设 - 如果表中有多行,它将返回 a CustomerId,但不能保证是哪一个.
    • @Damien_The_Unbeliever - 好吧,我会尝试澄清一下:它将从最后一行返回 CustomerId。是的,没有ORDER BY,不知道最后一行是什么。
    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多