I am trying to create a SQL script that fills a table with a new primary key.
what i currently have from internet searches is the following
DECLARE #IntVariable int;
DECLARE #Stringkey varchar(2);
DECLARE #SQLString nvarchar(500);
DECLARE #Intupdater nvarchar(500);
SET #IntVariable = 00000001;
SET #Stringkey = 'CD';
SET #SQLString = N'UPDATE Tri_Damen_Live.trimergo.calendar_details SET details_key = #Stringkey + #IntVariable';
SET #Intupdater = N'#IntVariable = #IntVariable+1'
EXECUTE sp_executesql #SQLString , N'#IntVariable INT' , N'#Stringkey VARCHAR(2)', #IntVariable, #Stringkey;
The errors I get with this are
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '='.
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "#Stringkey".
I have a few questions about my problem and hope someone might be able to help me
First question : it seems my int increaser is wrong. is there a way to make a update variable statement for the int?
Second : I declared the int as 00000001. But I doubt it stays like this. The reason I do this is because the key needs to be a set 10 characters long in total (example 'CD00000001' etc) does this work like this or is there another way?
Third question : as the topic stated. The 'Must declare the scalar variable "#Stringkey".' error. I have removed the stringkey part but then it says the same error about the Int variable. I declared them at the top and set them as well. What am I missing?
Side information :
this function will be used for multiple databases with varying table sizes. So I need this kind of function to account that it does not have a set amount of update statements.
The primary key that is created here must be a string (Varchar(10)) that is ALWAYS 10 characters long. Seems like a silly requirement but it has been chosen to use this system.
I am using Microsoft SQL Server 2012 to run this in.
1 You can't add an int to a string like that. You need to convert the int to a string
#Stringkey + convert(varchar(10),#IntVariable)
2 An int is a number. If you want it to be formatted, you need to do that yourself.
SET details_key = #Stringkey + right(''0000000000''+convert(varchar(8),#IntVariable),8)
3 Your variable declaration in sp_executesql should be
N'#IntVariable INT, #Stringkey VARCHAR(2)'
ie
EXECUTE sp_executesql #SQLString , N'#IntVariable INT, #Stringkey VARCHAR(2)', #IntVariable, #Stringkey;
Alternatively, you might consider using a SEQUENCE - see http://raresql.com/2013/06/21/sql-server-2012-how-to-generate-a-varchar-sequence-number-using-sequence-object/
The second parameter to sp_executesql should be a single string containing all parameter definitions:
EXECUTE sp_executesql #SQLString , N'#IntVariable INT,#Stringkey VARCHAR(2)', #IntVariable, #Stringkey;
SET #SQLString = N'UPDATE Tri_Damen_Live.trimergo.calendar_details SET details_key = #Stringkey + #IntVariable';
You are trying to concat #Stringkey + #IntVariable => (string + int) where you should convert the #IntVariable to varchar
Related
I am trying to run the below script in SQL Server Management Studio:
DECLARE #counter INT = 1
EXEC('SET '+#counter+' = '+#counter+' + 1')
However, I get this error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '1'-
I have been troubleshooting for days but gotten nowhere - I guess most likely TSQL simply does not accept this inside an EXEC command, but what could I potentially replace it with?
This is a part of a larger script where the above MUST be inside an EXEC statement in order for the rest to work..
This isn't going to working for a number of reasons.
Let's start with what you have:
DECLARE #counter INT = 1
EXEC('SET '+#counter+' = '+#counter+' + 1')
EXEC is expecting a string inside the parenthesis, yet you have an int (the variable #counter), so that is your first problem. Oddly, however, you aren't getting a conversion error here; it seems that #counter is being interpreted as its value (1), rather than Data Type Precedence being applied first. (If you try SELECT 'SET '+#counter+' = '+#counter+' + 1' you'll get the error "Conversion failed when converting the varchar value 'SET ' to data type int.").
Even if the query successfully got past that hurdle, that would cause another error because the query becomes:
SET 1 = 1 + 1
Obviously that isn't going to work, 1 is 1, no other number.
Next, a variable declared outside of the scope of a "dynamic" statement can't be referenced inside it. Let's take the following:
DECLARE #Varible int = 1;
EXEC (N'SELECT #Variable;');
This returns the error:
Must declare the scalar variable "#Variable".
If you are using a "dynamic" statement (your statement isn't dynamic at all), then you need to parametrise the variables. This is why you shouldn't be using EXEC ({SQL Statement}) and should be using sys.sp_executesql.
So, for the above, you get:
DECLARE #counter INT = 1;
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'SET #Variable = #Variable + 1;';
EXEC sys.sp_executesql #SQL, N'#Variable int OUTPUT',#Variable = #counter OUTPUT;
SELECT #Counter;
As I mentioned, that is all pointless, as there's nothing dynamic in the above, and your query should just be:
DECLARE #counter INT = 1;
SET #counter = #counter + 1;
Of course, none of this even goes on to address things like how to safely inject objects into a dynamic statement, but that isn't what this question is about. As I mention, the dynamic statement here is redundant, as it isn't dynamic, and it's not that required deferred parsing (such as when you ALTER a table to add a column, and then try to reference that column in the same batch).
If you run the script below, it'll throw an error like
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#counter".
BEGIN
DECLARE #counter INT = 1
EXEC('SET #counter = '+ #counter+' + 1')
END
WHY?
Because dynamic SQL is a different scope to the outer.
So can try this way (using output)
DECLARE #counter INT = 1
DECLARE #SQL nvarchar(50) = 'SELECT #counter2 =' + CAST(#counter + 1 AS VARCHAR(100))
exec sp_executesql #SQL, N'#counter2 int out', #counter out
SELECT #counter
I have a table dbo.t_products and I want to know the last record updated. For that I have an attribute last_changed which stores for each record the timestamp of the last update.
Finally I want to save that result in a variable called #y.
DECLARE #y DATETIME
DECLARE #p_table VARCHAR(100)
SET #p_table = 'dbo.t_products'
EXECUTE sp_executesql N'SET #y = SELECT MAX(last_changed) FROM #p_table'
,N'#p_table VARCHAR, #y DATETIME OUTPUT'
,#p_table
,#y OUTPUT
SELECT #y
The system returns the following message:
Msg 156, Level 15, State 1, Line 25
Incorrect syntax near the keyword 'SELECT'.
Any ideas?
The whole point of using dynamic SQL in your case (I assume) is to allow the use of a dynamic table name. In which case you have to insert the table name into the dynamic SQL string - you can't pass it in as a parameter, thats the problem you are trying in the first place.
Also you don't need a SET followed by a SELECT just use SELECT directly to set the variable.
Finally you definitely want to use the QUOTENAME function to escape your table name and avoid an SQL injection attack - this requires you split the table name and schema name.
DECLARE #y DATETIME;
DECLARE #p_schema VARCHAR(100);
DECLARE #p_table VARCHAR(100);
DECLARE #SQL NVARCHAR(max);
SET #p_schema = 'dbo';
SET #p_table = 't_products';
-- Add the table name to the dynamic SQL
SET #SQL = 'SELECT #y = MAX(last_changed) FROM ' + QUOTENAME(#p_schema) + '.' + QUOTENAME(#p_table);
EXECUTE sp_executesql #SQL, N'#y DATETIME OUTPUT', #y OUTPUT;
-- PRINT(#SQL); --- Debugging
SELECT #y;
I created the procedure listed below:
CREATE procedure getdata
(
#ID int,
#frm varchar(250),
#to varchar(250)
)
AS
BEGIN
DECLARE #SQL nvarchar(500)
set #SQL = 'select'
set #SQL = #SQL + ' EmpName, Address, Salary from Emp_Tb where 1=1 '
IF (#ID <> '' and #ID is not null)
Begin
SET #sql=#sql+' AND Emp_Id_Pk=' +#ID
End
END
print #sql
--execute (#sql)
I try to execute it using:
**execute getdata 3,'','';**
But I'm getting the following error:
Conversion failed when converting the nvarchar value 'select EmpName,
Address, Salary from Emp_Tb where 1=1 AND Emp_Id_Pk=' to data type int
Please help.
You are trying to concatenate a string and an integer.
You need to cast #ID as a string.
try:
SET #sql=#sql+' AND Emp_Id_Pk=' + CAST(#ID AS NVARCHAR(10))
Try Using
CONVERT(nvarchar(10),#ID)
This is similar to cast but is less expensive(in terms of time consumed)
I was using a KEY word for one of my columns and I solved it with brackets []
I use the latest version of SSMS or sql server management studio. I have a SQL script (in query editor) which has about 100 lines of code. This is error I got in the query:
Msg 245, Level 16, State 1, Line 2
Conversion failed when converting the nvarchar value 'abcd' to data type int.
Solution - I had seen this kind of error before when I forgot to enclose a number (in varchar column) in single quotes.
As an aside, the error message is misleading. The actual error on line number 70 in the query editor and not line 2 as the error says!
don't use string concatenation to produce sql, you can use sp_executesql system stored prcedure to execute sql statement with parameters
create procedure getdata #ID int, #frm varchar(250), #to varchar(250) as
begin
declare #sql nvarchar(max), #paramDefs nvarchar(max);
set nocount on;
set #sql = N'select EmpName, Address, Salary from Emp_Tb where #id is null or Emp_Id_Pk = #id';
set #paramDefs = N'#id int';
execute sp_executesql #sql, #paramDefs, #id = #ID;
end
see sp_executesql
I got this error when I used a where clause which looked at a nvarchar field but didn't use single quotes.
My invalid SQL query looked like this:
SELECT * FROM RandomTable WHERE Id IN (SELECT Id FROM RandomTable WHERE [Number] = 13028533)
This didn't work since the Number column had the data type nvarchar. It wasn't an int as I first thought.
I changed it to:
SELECT * FROM RandomTable WHERE Id IN (SELECT Id FROM RandomTable WHERE [Number] = '13028533')
And it worked.
You got this Error because you tried to convert column DataType from String to int which is
leagal if and only if
you dont have row in that table with string content inside that column
so just make sure your previously inserted Rows is compatible with the new changes
I have faced to the same problem, i deleted the constraint for the column in question and it worked for me. You can check the folder Constraints.
Capture :
You must use CONCAT and not the +
SET #sql = CONCAT(#sql,' AND Emp_Id_Pk=' ,#ID )
I'm currently having trouble writing a stored procedure and setting the value of a variable of type int to the results of a select statement with a variable as the tablename. I've looked at old threads and tried multiple methods, but no luck. If I'm not getting an error regarding the tablename, I end up getting an error with a variable conversion issue. I've been working on this for too long and any help would be appreciated. Below is a portion of my code. Thanks
DECLARE #BATCHNUMBER VARCHAR --value set in earlier code
DECLARE #ETABLE VARCHAR(50); --the table name
DECLARE #FIRSTDOCID INT;
SET #ETABLE = 'tablename_' + #BATCHNUMBER; --CREATE FIRST TABLE NAME
SELECT #FIRSTDOCID = MIN(D0CID) FROM #ETABLE
The error I get is: Must declare the table variable "#ETABLE"
You are trying to select from a VARCHAR, not a table. The only way to make this work is by using Dynamic SQL.
DECLARE #SQL NVARCHAR(250);
SET #SQL = 'SELECT #OUTPUT = MIN(D0CID) FROM ' + QuoteName(#ETABLE);
EXEC sp_executeSql #SQL, N'#output INT OUTPUT', #FIRSTDOCID OUTPUT;
SELECT #FIRSTDOCID;
However, I would not suggest using Dynamic SQL as this often leads to SQL injection.
You'll probably have to do something like use exec if you're dynamically building the query:
SET #QUERY = "SELECT" + ...etc.
exec(#QUERY)
Since ETABLE is a varchar, and not, as expected, a 'table variable'.
#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