100

@RowFrom int

@RowTo int

are both Global Input Params for the Stored Procedure, and since I am compiling the SQL query inside the Stored Procedure with T-SQL then using Exec(@sqlstatement) at the end of the stored procedure to show the result, it gives me this error when I try to use the @RowFrom or @RowTo inside the @sqlstatement variable that is executed.. it works fine otherwise.. please help.

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

Also, I tried including the following in the @sqlstatement variable:

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

but @RowTo still doesn't pass its value to @Rt and generates an error.

hofnarwillie
  • 3,563
  • 10
  • 49
  • 73
bill
  • 1,091
  • 2
  • 8
  • 9
  • 9
    I won't add an answer because it doesn't apply to this question specifically, but as the first result on google for this error it's worth noting that using `GO` causes a new branch where declared variables aren't visible past the statement. – IronSean Jul 21 '17 at 14:21

11 Answers11

91

You can't concatenate an int to a string. Instead of:

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

You need:

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

To help illustrate what's happening here. Let's say @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;

In order to build that into a string (even if ultimately it will be a number), I need to convert it. But as you can see, the number is still treated as a number when it's executed. The answer is 25, right?

In your case you can use proper parameterization rather than use concatenation which, if you get into that habit, you will expose yourself to SQL injection at some point (see this and this:

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

EXEC sys.sp_executesql @sql,
  N'@RowFrom int, @RowTo int',
  @RowFrom, @RowTo;
Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • 2
    Thanks, but what does the N' do? – bill Aug 24 '11 at 21:02
  • 3
    It makes sure that your `@sql` variable is interpreted correctly as `NVARCHAR` - a requirement if using `sp_executesql`... – Aaron Bertrand Aug 24 '11 at 21:03
  • 1
    Well they need to be Int because its being used like this "Where RowNum Between @RowFrom and @RowTo" The param @RowFrom/@RowTo is int, as well as the Declared.. – bill Aug 24 '11 at 21:06
  • 4
    Yes, understood. You are building a SQL string, and you are on two levels of scope. At the top level, you are building a string - all that concatenation needs to be with string values, regardless of whether they are '5' or 'foo' or 'zuluxxy'. I'll add an example to illustrate. – Aaron Bertrand Aug 24 '11 at 21:09
28

You can also get this error message if a variable is declared before a GOand referenced after it.

See this question and this workaround.

Pierre C
  • 2,920
  • 1
  • 35
  • 35
6

Just FYI, I know this is an old post, but depending on the database COLLATION settings you can get this error on a statement like this,

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

if for example you typo the S in the

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

sorry to spin off the answers already posted here, but this is an actual instance of the error reported.

Note also that the error will not display the capital S in the message, I am not sure why, but I think it is because the

Set @sql =

is on the left of the equal sign.

htm11h
  • 1,739
  • 8
  • 47
  • 104
6

This is most likely not an answer to the issue itself, but this question pops up as first result when searching for Sql declare scalar variable hence I want to share a possible solution to this error.

In my case this error was caused by the use of ; after a SQL statement. Just remove it and the error will be gone.

I guess the cause is the same as @IronSean already posted in a comment above:

it's worth noting that using GO (or in this case ;) causes a new branch where declared variables aren't visible past the statement.

For example:

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
ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
  • 1
    This must be something _very specific_ to the editor you're using, or you've changed the batch separator in SSMS from `GO` to `;`. In T-SQL we are highly encouraged to always use a statement terminator (`;` is not a _batch_ terminator), and in fact there are many scenarios where you _have_ to use it. So I do not agree that removing it is a solution. – Aaron Bertrand Sep 29 '21 at 12:06
  • This should be considered as a hint. I have this issue in SSMS to this day and never have changed a setting, everything is default. – ViRuSTriNiTy Sep 30 '21 at 14:11
  • There's something you're not telling us (do you have any SSMS add-ins installed?) because there is no way a semi-colon is going to be considered a batch separator by SSMS on its own unless you tell it to. – Aaron Bertrand Sep 30 '21 at 14:28
  • (Though in your specific case it might be more related to mixing up `@id` and `@var`.) – Aaron Bertrand Sep 30 '21 at 17:59
  • This was my issue. Using `mssql-cli` – Chris Jan 10 '23 at 17:17
  • Thats it! SQLFiddle was driving me crazy till I simply removed the ; - characters. – Carsten Jul 27 '23 at 12:47
4

Sometimes, if you have a 'GO' statement written after the usage of the variable, and if you try to use it after that, it throws such error. Try removing 'GO' statement if you have any.

3

Just adding what fixed it for me, where misspelling is the suspect as per this MSDN blog...

When splitting SQL strings over multiple lines, check that that you are comma separating your SQL string from your parameters (and not trying to concatenate them!) and not missing any spaces at the end of each split line. Not rocket science but hope I save someone a headache.

For example:

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;
EBH
  • 10,350
  • 3
  • 34
  • 59
Tim Tyler
  • 2,380
  • 2
  • 16
  • 13
1

Case Sensitivity will cause this problem, too.

@MyVariable and @myvariable are the same variables in SQL Server Man. Studio and will work. However, these variables will result in a "Must declare the scalar variable "@MyVariable" in Visual Studio (C#) due to case-sensitivity differences.

0

Just an answer for future me (maybe it helps someone else too!). If you try to run something like this in the query editor:

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'

And you get the error:

Must declare the scalar variable "@year"

That's because you are trying to run a bunch of code that includes BOTH the stored procedure execution AND the query below it (!). Just highlight the one you want to run or delete/comment out the one you are not interested in.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
saiyancoder
  • 1,285
  • 2
  • 13
  • 20
0

If someone else comes across this question while no solution here made my sql file working, here's what my mistake was:

I have been exporting the contents of my database via the 'Generate Script' command of Microsofts' Server Management Studio and then doing some operations afterwards while inserting the generated data in another instance.

Due to the generated export, there have been a bunch of "GO" statements in the sql file.

What I didn't know was that variables declared at the top of a file aren't accessible as far as a GO statement is executed. Therefore I had to remove the GO statements in my sql file and the error "Must declare the scalar variable xy" was gone!

pbur
  • 85
  • 7
0

As stated in https://learn.microsoft.com/en-us/sql/t-sql/language-elements/sql-server-utilities-statements-go?view=sql-server-ver16 , the scope of a user-defined variable is batch dependent .

--This will produce the error

 GO   
    DECLARE @MyVariable int;
    SET @MyVariable = 1;
    GO --new batch of code
    SELECT @MyVariable--CAST(@MyVariable AS 
    int);
 GO

--This will not produce the error

 GO   
   DECLARE @MyVariable int;
   SET @MyVariable = 1;
   SELECT @MyVariable--CAST(@MyVariable AS int);
 GO

We get the same error when we try to pass a variable inside a dynamic SQL:

GO
DECLARE @ColumnName VARCHAR(100),
        @SQL NVARCHAR(MAX);
SET @ColumnName = 'FirstName';
EXECUTE ('SELECT [Title],@ColumnName FROM Person.Person');  
GO

--In the case above @ColumnName is nowhere to be found, therefore we can either do:

EXECUTE ('SELECT [Title],' +@ColumnName+ ' FROM Person.Person');

or

GO
DECLARE @ColumnName VARCHAR(100),
        @SQL NVARCHAR(MAX);
SET @ColumnName = 'FirstName';
SET @SQL = 'SELECT ' + @ColumnName + ' FROM Person.Person';
EXEC sys.sp_executesql @SQL  
GO
-1

Give a 'GO' after the end statement and select all the statements then execute

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 29 '21 at 19:34