【问题标题】:Must declare the scalar variable必须声明标量变量
【发布时间】:2011-11-03 03:54:45
【问题描述】:

@RowFrom int

@RowTo int

都是存储过程的全局输入参数,因为我使用 T-SQL 编译存储过程中的 SQL 查询,然后在存储过程的末尾使用 Exec(@sqlstatement) 来显示结果,所以它给了我这个当我尝试在执行的@sqlstatement 变量中使用@RowFrom 或@RowTo 时出错。否则它可以正常工作。请帮忙。

"Must declare the scalar variable "@RowFrom"."

另外,我尝试在 @sqlstatement 变量中包含以下内容:

'Declare @Rt int'
'SET @Rt = ' + @RowTo

但@RowTo 仍然没有将其值传递给@Rt 并产生错误。

【问题讨论】:

  • 我不会添加答案,因为它不适用于这个问题,但作为谷歌的第一个结果是这个错误值得注意的是,使用GO 会导致一个新的分支声明变量在语句之后不可见。

标签: sql sql-server stored-procedures


【解决方案1】:

您不能将 int 连接到字符串。而不是:

SET @sql = N'DECLARE @Rt int; SET @Rt = ' + @RowTo;

你需要:

SET @sql = N'DECLARE @Rt int; SET @Rt = ' + CONVERT(VARCHAR(12), @RowTo);

为了帮助说明这里发生了什么。假设@RowTo = 5。

DECLARE @RowTo int;
SET @RowTo = 5;

DECLARE @sql nvarchar(max);
SET @sql = N'SELECT ' + CONVERT(varchar(12), @RowTo) + ' * 5';
EXEC sys.sp_executesql @sql;

为了将它构建成一个字符串(即使最终它将是一个数字),我需要对其进行转换。但是正如你所看到的,该数字在执行时仍然被视为一个数字。答案是 25,对吧?

在您的情况下,您可以使用适当的参数化而不是使用连接,如果您养成这种习惯,您将在某些时候暴露自己的 SQL 注入(请参阅this 和 this:

SET @sql = @sql + ' WHERE RowNum BETWEEN @RowFrom AND @RowTo;';

EXEC sys.sp_executesql @sql,
  N'@RowFrom int, @RowTo int',
  @RowFrom, @RowTo;

【讨论】:

  • 谢谢,但是 N' 是做什么的?
  • 它确保您的@sql 变量被正确解释为NVARCHAR - 如果使用sp_executesql 则需要...
  • 好吧,它们需要是 Int,因为它的使用方式如下“@RowFrom 和 @RowTo 之间的 RowNum 位置”参数 @RowFrom/@RowTo 是 int,以及 Declared..
  • 是的,明白了。您正在构建一个 SQL 字符串,并且您处于两个级别的范围内。在顶层,您正在构建一个字符串 - 所有连接都需要与字符串值一起,无论它们是“5”、“foo”还是“zuluxxy”。我将添加一个示例来说明。
【解决方案2】:

仅供参考,我知道这是一篇旧帖子,但根据数据库 COLLATION 设置,您可能会在这样的语句中收到此错误,

SET @sql = @Sql + ' WHERE RowNum BETWEEN @RowFrom AND @RowTo;';

例如,如果您在

中打错了 S
SET @sql = @***S***ql 

很抱歉将此处已发布的答案分拆出来,但这是所报告错误的实际实例。

还要注意,错误不会在消息中显示大写的 S,我不知道为什么,但我认为是因为

Set @sql =

在等号的左边。

【讨论】:

    【解决方案3】:

    大小写敏感也会导致这个问题。

    @MyVariable 和 @myvariable 在 SQL Server Man 中是相同的变量。工作室并将工作。但是,由于区分大小写的差异,这些变量将导致“必须在 Visual Studio (C#) 中声明标量变量“@MyVariable”。

    【讨论】:

      【解决方案4】:

      只需添加为我修复的内容,根据this MSDN blog ,其中拼写错误是嫌疑人...

      将 SQL 字符串拆分为多行时,请检查您是否使用逗号将 SQL 字符串与参数分开(而不是尝试连接它们!),并且在每个拆分行的末尾没有遗漏任何空格。不是火箭科学,但希望我能免去一些人的头疼。

      例如:

      db.TableName.SqlQuery(
          "SELECT Id, Timestamp, User " +
          "FROM dbo.TableName " +
          "WHERE Timestamp >= @from " +
          "AND Timestamp <= @till;" + [USE COMMA NOT CONCATENATE!]
          new SqlParameter("from", from),
          new SqlParameter("till", till)),
          .ToListAsync()
          .Result;
      

      【讨论】:

        【解决方案5】:

        如果变量在 GO 之前声明并在其之后引用,您也会收到此错误消息。

        看到这个question和这个workaround。

        【讨论】:

          【解决方案6】:

          只是对未来我的回答(也许它也对其他人有帮助!)。如果您尝试在查询编辑器中运行类似的内容:

          USE [Dbo]
          GO
          
          DECLARE @RC int
          
          EXECUTE @RC = [dbo].[SomeStoredProcedure] 
             2018
            ,0
            ,'arg3'
          GO
          
          SELECT month, SUM(weight) AS weight, SUM(amount) AS amount 
          FROM SomeTable AS e 
          WHERE year = @year AND type = 'M'
          

          然后你得到错误:

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

          那是因为您正在尝试运行一堆代码,其中包含 BOTH 存储过程执行 AND 其下方的查询 (!)。只需突出显示您要运行的那个或删除/注释掉您不感兴趣的那个。

          【讨论】:

            【解决方案7】:

            如果其他人遇到这个问题,而这里没有解决方案使我的 sql 文件正常工作,这就是我的错误:

            我一直在通过 Microsoft 的 Server Management Studio 的“生成脚本”命令导出数据库的内容,然后在将生成的数据插入另一个实例的同时进行一些操作。

            由于生成导出,sql文件中出现了一堆“GO”语句。

            我不知道的是,只要执行 GO 语句,就无法访​​问在文件顶部声明的变量。 因此我不得不删除我的 sql 文件中的 GO 语句,并且错误“必须声明标量变量 xy”消失了!

            【讨论】:

              【解决方案8】:

              这很可能不是问题本身的答案,但是在搜索 Sql declare scalar variable 时会弹出这个问题作为第一个结果,因此我分享了解决这个错误的可能方法。

              在我的例子中,这个错误是由于在 SQL 语句之后使用 ; 引起的。只需删除它,错误就会消失。

              我猜原因与上面评论中已经发布的@IronSean 相同:

              值得注意的是,使用 GO(或者在这种情况下;)会导致一个新分支,其中声明的变量在语句之后不可见。

              例如:

              DECLARE @id int
              SET @id = 78
              
              SELECT * FROM MyTable WHERE Id = @var; <-- remove this character to avoid the error message
              SELECT * FROM AnotherTable WHERE MyTableId = @var
              

              【讨论】:

              • 这必须是您使用的编辑器非常具体的内容,或者您​​已将 SSMS 中的批处理分隔符从 GO 更改为 ;。在 T-SQL 中,我们强烈建议始终使用语句终止符(; 不是 batch 终止符),事实上在很多情况下您必须用它。所以我不同意删除它是一个解决方案。
              • 这应该被视为一个提示。直到今天我在 SSMS 中也遇到了这个问题,并且从未更改过设置,一切都是默认设置。
              • 有些事情您没有告诉我们(您是否安装了任何 SSMS 插件?)因为分号本身不会被 SSMS 视为批处理分隔符除非你告诉它。
              • (尽管在您的具体情况下,它可能与混淆@id 和@var 更相关。)
              【解决方案9】:

              有时,如果您在使用变量后编写了“GO”语句,并且在此之后尝试使用它,则会引发此类错误。如果有任何“GO”语句,请尝试删除。

              【讨论】:

                【解决方案10】:

                在结束语句后给出一个'GO'并选择所有语句然后执行

                【讨论】:

                • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-07-03
                • 1970-01-01
                相关资源
                最近更新 更多