必须声明标量变量


79

@RowFrom int

@RowTo int

都是存储过程的全局输入参数,并且由于我正在用T-SQL编译存储过程内部的SQL查询,然后Exec(@sqlstatement)在存储过程的末尾使用来显示结果,因此当我尝试使用时会出现此错误在@RowFrom@RowTo@sqlstatement被执行的变量..它工作正常,否则..请帮助。

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

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

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

@RowTo仍然不会将其值传递给它@Rt 并生成错误。


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

Answers:


74

您不能将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字符串内重新声明@Rt等,您只需要说:

SET @sql = @sql + ' WHERE RowNum BETWEEN ' 
    + CONVERT(varchar(12), @RowFrom) + ' AND ' 
    + CONVERT(varchar(12), @RowTo);

尽管最好进行适当的参数化,例如

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

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

2
谢谢,但是N'是做什么的?
法案

3
它可以确保将@sql变量正确解释为NVARCHAR-使用sp_executesql...时的要求
Aaron Bertrand

1
好吧,他们需要是Int,因为它的用法是这样的:“ @ RowFrom和@RowTo之间的RowNum”参数@ RowFrom / @ RowTo是int以及声明的。.–
法案

4
是的,了解。您正在构建一个SQL字符串,并且处于两个范围的范围内。在顶层,您正在构建一个字符串-所有串联都需要带有字符串值,而不管它们是'5'还是'foo'还是'zuluxxy'。我将添加一个示例进行说明。
亚伦·伯特兰


6

仅供参考,我知道这是一篇过时的文章,但是根据数据库的COLLATION设置,您可能会在这样的语句中遇到此错误,

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

例如,如果您在

SET @sql = @***S***ql 

很抱歉,无法提供此处已经发布的答案,但这是所报告错误的实际实例。

另请注意,该错误不会在消息中显示大写字母S,我不确定为什么,但是我认为这是因为

Set @sql =

在等号的左侧。


3

只需添加对我而言已解决的问题,根据此MSDN博客,拼写错误是可疑的...

将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;

0

区分大小写也会导致此问题。

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


0

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

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执行存储过程它下面的查询(!)。只需突出显示您要运行的那个或删除/注释不感兴趣的那个即可。


0

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

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

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

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


0

这很可能不是问题本身的答案,但搜索时此问题会作为第一个结果弹出 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.