【问题标题】:SQL Server Error: "Must Declare Scalar Variable"SQL Server 错误:“必须声明标量变量”
【发布时间】:2016-06-28 07:53:27
【问题描述】:

真的很傻,但我正在尝试编写一个 SQL Server 脚本,该脚本创建一个存储过程,将酒店房间的 RackRate 降低 6.66%。当我去执行存储过程时,我不断收到以下错误:

必须声明标量变量“@NewRackRate”。

任何帮助将不胜感激。

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE SPECIFIC_NAME = 'sp_UpdateRackRate')
    DROP PROCEDURE sp_UpdateRackRate;
GO

CREATE PROC sp_UpdateRackRate
    @RackRate smallmoney
AS
BEGIN
    DECLARE @NewRackRate smallmoney;
    DECLARE @OldRackRate smallmoney = (SELECT RackRate FROM RackRateTable);

    UPDATE RackRateTable
    SET @NewRackRate = @OldRackRate - (@OldRackRate * .0666)
END
GO

EXEC sp_UpdateRackRate
      @RackRate = @NewRackRate;    // How do I access @NewRackRate?

【问题讨论】:

  • 除非我有误解,否则您希望 @NewRackRate 成为存储过程中的 OUTPUT 参数。
  • @NewRackRate 在 BEGIN 之后声明,并在到达相应的 END 时超出范围。您只能在其范围内使用它。一个 END 到达,它不再存在,你不能在 EXEC 调用中使用它。
  • @KenWhite,我就是这么想的。如何全局声明?
  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!
  • 您的程序根本没有意义。首先,除非RackRateTable 仅包含一行,否则您的第二个声明应返回错误。其次,您的更新语句正在设置一个变量而不是列,第三,您的参数可能应该被声明为输出参数,正如 ZLK 所写的那样。

标签: sql-server


【解决方案1】:

我猜你想从你的存储过程中输出@NewRackRate。根据提供的示例,这里有一个快速的方法......

CREATE PROC sp_UpdateRackRate
      @NewRackRate smallmoney OUTPUT
AS BEGIN
    SELECT @NewRackRate = RackRate * 0.0334 FROM RackRateTable;
END
GO

DECLARE @RackRate smallmoney;
EXEC sp_UpdateRackRate @RackRate OUTPUT;
--SELECT @RackRate;

不过,实际上,您不需要为此使用存储过程。简单来说,

DECLARE @RackRate smallmoney;
SELECT @RackRate = RackRate * 0.0334 FROM RackRateTable;
--SELECT @RackRate;

【讨论】:

  • 谢谢你,@ZLK!我想要做的是更新 RackRateTable,然后通过编写 SELECT * FROM RackRateTable 来显示我的结果。你会怎么做呢?
  • 如果你想更新 RackRateTable,使 RackRates 为 0.0334 * 当前的 RackRate,你可以做一个简单的更新过程。例如UPDATE RackRateTable SET RackRate = 0.0334 * RackRate;如果你想存储之前的值进行比较,你可以输出更新过程的结果,或者创建一个额外的列来存储旧值,并将该列更新为当前的机架率,例如SET OldRackRate = RackRate, RackRate = 0.0334 * RackRate
【解决方案2】:
/*
drop table rackratetable;
create Table rackratetable (ID int ,rackrate smallmoney)
truncate table rackratetable
insert into rackratetable values (1,100.00)

drop procedure PUpdateRAckRAte ;
CREATE procedure PUpdateRackRate 
@adjustment smallmoney ,                --input parameter
@updatedrackrate smallmoney OUTPUT      --output parameter
as

update  rackratetable
    set rackrate = rackrate * @adjustment

select @updatedrackrate = rackrate from rackratetable
--select @updatedrackrate
return

*/
set nocount on
truncate table rackratetable
insert into rackratetable values (1,100.00)

declare @newrate smallmoney
exec  PUpdateRackRate 
    @adjustment = 0.666,                      --Input parameter
    @updatedrackrate     = @newrate OUTPUT    --Returned from procedure note the counterintuitiveness

select 'Updated rack rate is ' + cast(@newrate as varchar(max))

【讨论】:

    【解决方案3】:
    IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE SPECIFIC_NAME = 'sp_UpdateRackRate')
        DROP PROCEDURE sp_UpdateRackRate;
    
    GO
    
    CREATE PROC sp_UpdateRackRate
        @RackRate           smallmoney
    
    AS
    
    BEGIN
    
    DECLARE @NewRackRate smallmoney;
    DECLARE @OldRackRate smallmoney = (SELECT Top 1 RackRate FROM RackRate);
    
    UPDATE RackRateTable
        SET NewRackRate = @OldRackRate - (@OldRackRate * .0666)
    
    END
    select (@OldRackRate - (@OldRackRate * .0666)) NewRackRate
    GO
    
    EXEC sp_UpdateRackRate 100.06
    

    【讨论】:

    • 如果您发布代码、XML 或数据示例,在文本编辑器中突出显示这些行,然后单击编辑器上的“代码示例”按钮 ({ })工具栏以很好地格式化和语法突出显示它!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多