【问题标题】:How to call a SQL Server procedure with both input and output parameters?如何使用输入和输出参数调用 SQL Server 过程?
【发布时间】:2019-10-08 06:30:23
【问题描述】:

我正在尝试编写一个基于选择查询结果返回值的过程。与查找用户 ID 一样,使用名字和姓氏来定位用户 ID,并将 ID 作为 OUTPUT 参数返回。如果找到多个用户或没有找到用户,则设置返回值 -1,并将 OUTPUT 参数设置为 0。

我尝试了以下代码,但出现错误:

必须声明标量变量“@intValue”

我在互联网上搜索过,但没有一个能解决我的问题。

CREATE PROCEDURE GetIdOfUser
    (@f_name VARCHAR(50), 
     @l_name VARCHAR(50),
     @outValue INT OUTPUT)
AS
    DECLARE @intValue INT;

    SELECT @intValue = userID 
    FROM users
    WHERE firstName = @f_name AND lastName = @l_name

    IF @@rowcount > 1 -- more than one user?
    BEGIN
        SET @outValue = 0
        RETURN -1;
    END

    IF @@rowcount == 1
    BEGIN
        SET @outValue = @intValue;
    END



DECLARE @myretValue INT;

EXEC GetIdOfUser 'raj', 'ahuja', @myretValue;

SELECT @myretValue;

我正在使用 SQLfiddle[sqlfiddle.com] 来学习 SQL Server 概念。我对在 SQL Server 中创建过程非常陌生,因此我们将不胜感激。

编辑 1:SQL Server 版本为 2017

编辑 2: 我正在使用的架构和示例数据。

create table users
(
    userID int,
    firstName varchar(50),
    lastName varchar(50),
    title varchar(50)
);

insert into users(userID, firstName, lastName, title) 
values(501, 'natasha', 'ghosh', 'title1'),
      (502, 'raj', 'ahuja', 'title2'),
      (503, 'katy', 'perry', 'title3'),
      (504, 'john', 'cyrus', 'title4'),
      (505, 'anindita', 'pal', 'title5');

【问题讨论】:

  • IF @@rowcount == 1 应该是 IF @@rowcount = 1。不知道为什么会出现错误。
  • 你的 @@ROWCOUNT 被重置为 0。将其更改为 else 块...然后正确调用它。 See the demo here。 @@ROWCOUNT 可能很棘手。 See this blog 在一个实例上。此外,使用 PRINT 会将其重置为 0。
  • 它可以工作@Diksha...See the demo here 我只是在过程中更改了表名。请注意,这是我在之前的 cmets 中已经建议的编辑。
  • 哦,我敢打赌,我知道这里有什么问题。 @Diksha return 语句与输出变量是一种非常不同的动物。我有一种感觉,您希望在输出变量中看到返回值。程序不是这样运作的。它有一个返回值,应该用于执行状态,而不是返回数据。然后你有完全不同的输出参数。你可以有很多,它们可以是任何数据类型。返回值始终是 int。
  • @Diksha 是的,这是正确的。

标签: sql-server stored-procedures parameter-passing


【解决方案1】:

我会稍微简化一下。无需在此处填充多个变量。看看像这样简单一点的方法是否可行。

CREATE PROCEDURE GetIdOfUser
(
    @f_name VARCHAR(50), 
    @l_name VARCHAR(50),
    @outValue INT OUTPUT
)
AS
    SELECT @outValue = userID 
    FROM users
    WHERE firstName = @f_name 
        AND lastName = @l_name

    if @@rowcount > 1
        set @outValue = -1

GO

这是你将如何使用它。

DECLARE @myretValue INT;

EXEC GetIdOfUser 'raj', 'ahuja', @myretValue OUTPUT;

SELECT @myretValue;

--编辑--

对于您的新示例数据,我决定使用表名专家,因为您发布了两个不同的名称。我在这里发布的过程完美无缺。

create table specialist(
userID int,
firstName varchar(50),
lastName varchar(50),
title varchar(50)
);
insert into specialist(userID, firstName, lastName, title) values(501, 'natasha', 'ghosh', 'title1');
insert into specialist(userID, firstName, lastName, title) values(502, 'raj', 'ahuja', 'title2');
insert into specialist(userID, firstName, lastName, title) values(503, 'katy', 'perry', 'title3');
insert into specialist(userID, firstName, lastName, title) values(504, 'john', 'cyrus', 'title4');
insert into specialist(userID, firstName, lastName, title) values(505, 'anindita', 'pal', 'title5');

GO

CREATE PROCEDURE GetIdOfUser
(
    @f_name VARCHAR(50), 
    @l_name VARCHAR(50),
    @outValue INT OUTPUT
)
AS
    SELECT @outValue = userID 
    FROM specialist
    WHERE firstName = @f_name 
        AND lastName = @l_name

    if @@rowcount > 1
        set @outValue = -1

GO

DECLARE @myretValue INT;

EXEC GetIdOfUser 'raj', 'ahuja', @myretValue OUTPUT;

SELECT @myretValue;

【讨论】:

  • 是的,这次运行但没有返回任何结果@Sean Lange
  • 请看我的更新。我添加了调用它的示例代码。
  • 使用我刚刚发布的代码出现该错误的可能性为零。该变量名不在代码中。
  • 您是否也将程序更改为我发布的代码?
  • 输出变量中没有值?这并不难,但您没有在此处提供信息。您需要说明发生了什么,而不是“我遇到错误”或“它没有返回结果”。这个过程非常简单,它要么返回一个值,要么抛出一个异常。这里没有任何中间立场。
【解决方案2】:

试试这个

DECLARE @myretValue int
EXEC GetIdOfUser 'raj', 'ahuja', @myretValue output
select @myretValue;

【讨论】:

  • 试过了还是一样的错误:Must declare the scalar variable "@intValue".
  • 尝试删除行上多余的“=”符号。所以,这是正确的方式 IF @@rowcount = 1
  • 我创建了表 [Users] 以及您的存储过程。该过程执行没有任何错误。您是否知道您使用的是哪个 SQL Server 版本?我在 SQL Server 2008 - 2012 上测试过
  • @DarkoMartinovic @@ROWCOUNT 在第一个 IF 块之后被重置。这就是为什么第二个条件总是错误的。它将正确执行,但不会返回正确的结果。
  • @scsimon 错误“必须声明标量变量“@intValue””是如何引发的?
【解决方案3】:

您有多个问题,我会尽量减少更改。

CREATE PROCEDURE GetIdOfUser
    (@f_name VARCHAR(50), 
     @l_name VARCHAR(50),
     @outValue INT OUTPUT)
AS
    DECLARE @intValue INT

默认情况下 sql fiddle 使用 ; 结束批处理,将其更改为 GO 或删除 ;

    SELECT @intValue = userID 
    FROM users
    WHERE firstName = @f_name AND lastName = @l_name

    SET @outValue = CASE WHEN @@rowcount = 1 THEN @intValue ELSE 0 END

使用 case 语句简化了这一点,这里不需要多个 if 语句。此外,您的原始支票大于等于,不小于(当没有找到行时)并且在这种情况下会返回 0。这处理所有情况。

GO

结束批处理或下面的代码也成为程序的一部分。我相信将所有过程逻辑放在BEGIN ... END 中也可以。

DECLARE @myretValue INT

EXEC GetIdOfUser 'raj', 'ahuja', @myretValue OUTPUT

在过程调用中,您需要将输出变量定义为OUTPUT 才能实际工作,否则sql 不会设置变量的值。

SELECT @myretValue

使用上面的代码一切正常,我得到了回复502,小提琴链接 - http://sqlfiddle.com/#!18/ddb50/47

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2023-03-12
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多