I'm creating a report using sql scripts through management studio and I'm getting the error " Must Declare the scalar variable "#Account". I've been reading other similar questions on this portal but they are related to c#
I'm currently trying to reduce the code on the script so I decided to put a sql script into a variable because depending on a condition the where condition will change. Below is an example of the code
Declare #Account int = 1 , #SQL varchar(max)=''
Select #SQL = N'Select ColumnA,ColumnB, ColumnC from Table1 where ColumnA =1'
if #Account IS NULL
Begin
exec(#SQL)
end
--Here is where the error is hapening
else
begin
--This is the line causing the error
Select #SQL = #SQL + 'AND ColumnB=#Account"
exec(#SQL)
end
If I type manually the value of the variable next to "ColumnB=" it works but the account number will be selected by the user executing the script. I'm thinking on maybe building a temp table to capture the variable value and then do a sub query on the where condition but maybe the solution to this error may be more easier
You want sp_executesql:
select #SQL = #SQL + 'AND ColumnB=#Account';
exec sp_executesql #SQL, N'#Account int', #Account=#Account;
This is how you pass parameters into a dynamic SQL statement in SQL Server. I strongly recommend that you only use sp_executesql to execute SQL statements -- even when you don't have parameters. Using it makes it easy to implement parameters when you need them.
You are passing in '#Account' into the #SQL variable -- the underlying EXEC cannot see that variable.
One way of fixing this would instead be to do this:
Select #SQL = #SQL + 'AND ColumnB=' + CAST(#Account as varchar)
I have a database with the name "Union". I am trying execute SQL for this database in the MAINT table but since 'union' is a SQL command it is throwing errors. I can get the query to run when executing from Union database. Would dynamic SQL be able to fix my problem or should I change the database name?
I keep getting incorrect syntax near keyword 'UNION' here is what I have so far,
DECLARE #sql varchar(max)
DECLARE #Database varchar(5)
Set #Database = 'UNION'
SELECT #sql = 'SELECT '+#Database+' as ''Database'', '+#Database+'.hsi.useraccount.username as ''User Name'',
'+#Database+'.hsi.useraccount.realname as ''Real Name''
FROM '+#Database+'.hsi.useraccount
WHERE '+#Database+'.hsi.useraccount.username NOT LIKE ''%deactivated%'' and '+#Database+'.hsi.useraccount.username not like ''%administrator'' and '+#Database+'.hsi.useraccount.username not like ''%internal%'''
execute(#sql)
Add [] brackets around Schema names.
SELECT #sql = REPLACE('SELECT [#Database] as ''Database'', [#Database].hsi.useraccount.username as ''User Name'',
[#Database].hsi.useraccount.realname as ''Real Name''
FROM [#Database].hsi.useraccount
WHERE [#Database].hsi.useraccount.username NOT LIKE ''%deactivated%'' and [#Database].hsi.useraccount.username not like ''%administrator'' and [#Database].hsi.useraccount.username not like ''%internal%'''
,'#Database',#Database)
As long as the text "#Database" text doesn't appear anywhere else in your select statement, just throw it into a REPLACE() function and avoid all that embedded quote syntax and string concatenation headache.
You also can use quotename instead of manually entering square brackets
declare #db nvarchar(100)
set #db='performance'
declare #sql nvarchar(max)
set #sql='select * from '+QUOTENAME(#db)+'.'+quotename('dbo')+'.'+QUOTENAME('orders')
print #sql
exec(#sql)
I have written a stored procedure where a table name and database name collect
using cursor from different two tables.
But my problem is when I run a query to find out a table exists in a database or not, then show a error.
Now how can I run the query and store output into a variable?
Declare #table_exist nvarchar(200),#val1 nvarchar(200),#return1 nvarchar(200);
SET #table_exist=
'SELECT 1 FROM '+#db_name+'.sys.tables
where name='+#table_name+'';
EXEC sp_executesql #table_exist,#return1 OUTPUT;
select #return1;
ERROR:
Invalid column name 'table name'
You should use quotename when building dynamic query:
SET #table_exist=
'SELECT 1 FROM '+ quotename(#db_name)+'.sys.tables
where name='+quotename(#table_name)+'';
When facing such an error the best would be to print #table_exists and see what is actually built.
I haven't looked properly at your query. You are missing apostrophes:
SET #table_exist=
'SELECT 1 FROM '+ quotename(#db_name)+'.sys.tables
where name=''' + #table_name +'''';
UPDATE:
When using output variable you should set it in a query:
SET #table_exist=
'SELECT #return1 = 1 FROM ' + quotename(#db_name) + '.sys.tables
where name='''+#table_name+'''';
To prevent result set from returning to client, create temporary table and insert result set into it. In this case this will leave only one result set, the result of select #return1:
declare #tbl table (exist bit)
insert into #tbl
EXEC sp_executesql #table_exist, N'#return1 nvarchar(200) out', #return1 OUT;
select #return1;
It is best to write your query by using ' and " properly . Which makes less mistakes while writing query.
The error on you code is that you are confused by using only '. Best to use ' for variable only.
Write your code as:
"SELECT 1 FROM ' "+#db_name+" '.sys.tables
where name=' "+#table_name+" ' ";
#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.
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;
You can also get this error message if a variable is declared before a GOand referenced after it.
See this question and this workaround.
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.
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.
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
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;
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.
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.
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!
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
Give a 'GO' after the end statement and select all the statements then execute
I've got this t-sql snippet:
DECLARE #db_name varchar(255);
SET #db_name = 'MY_DATABASE'; -- assuming there is database called 'my_database'
USE #db_name -- this line ends with error "Incorrect syntax near '#db'."
But USE with variable (third line of snippet) doesn't work.
Why it doesn't work?
You cannot provide the name of the database for USE statement in a variable.
As you have noticed, the USE statement does not accept a variable as parameter. The only alternative that quickly comes to mind is quite crude and extremely error prone, but here you go:
EXEC ('USE ' + #db_name + '
SELECT * FROM some_table
INSERT INTO some_table VALUES (1)')
I hope that someone else can do better :-)
SQL Server will not accept the USE statement with a variable.
To use database names dynamically, you have to create dynamic SQL statements with (almost) fully qualified names as follows:
Declare #SQL VarChar (100)
SET #SQL = 'SELECT * FROM ' + #DatabaseName + '.dbo.TableName'
and then you execute it using sp_SQLExec
The way I do this is with an if statement:
if #DBName = 'DB1'
<query with DB1>
else
<query with DB2>