Problem with a dynamic function in SQL Server - sql

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;

Related

TSQL SET command not working inside EXEC statement

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

Issues with equal sign when assigning statement to # variable for EXEC sp_executesql

Hello: I am trying to encapsulate the following Insert and select statement into a variable for SQL to run.
The issue occurs when the equals sign is included for evaluation (or right around there)
The CustomPollerAssignmentID Column had to be cast since it natively a PK and a uniqueidentifier (see image)
What must be done to have the statement evaluate properly when passes to the sp_executesql?
I receive a syntax error as illustrated below
declare
#date datetime,
#query nvarchar(Max)
set #date = getdate()-4
set #query = --'Insert into [SolarWindsOrion].[dbo].[BWC_VPN_Hourly_Long_Store]
'SELECT * FROM [SolarWindsOrion].[dbo].[CustomPollerStatistics_Hourly]
where Cast(CustomPollerAssignmentID as nvarchar(max)) = 63FEB60-4516-4C1A-9A11-DB30ACA44301'
EXEC sp_executesql #query
UPDATE-->
I tried adding the single quotes.
While the statement does execute.. no results are returned. See Image below
you need to put it in quote like this '63FEB60-4516-4C1A-9A11-DB30ACA44301' , so your adhoc query would look like this :
declare
#date datetime,
#query nvarchar(Max)
set #date = getdate()-4
set #query = --'Insert into [SolarWindsOrion].[dbo].[BWC_VPN_Hourly_Long_Store]
'SELECT * FROM [SolarWindsOrion].[dbo].[CustomPollerStatistics_Hourly]
where Cast(CustomPollerAssignmentID as nvarchar(max)) = ''63FEB60-4516-4C1A-9A11-DB30ACA44301'''
EXEC sp_executesql #query

Conversion failed when converting the nvarchar value ... to data type int

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 )

Dynamic Query is not working with cursor in SqlServer 2008 Stored Procedure

I am building a stored procedure in Sql Server 2008. Stored Procedure has two arguments which are the column names of a table. In stored procedure I used dynamic query for fetching data of these two columns with the help of Cursor.
Code:
Create PROCEDURE TestSP
(
#firstAttribute nvarchar(max),
#secondAttribute nvarchar(max)
)
AS
DECLARE #x FLOAT
DECLARE #y INT
DECLARE #query nvarchar(max)
DECLARE #cursor_query nvarchar(max)
DECLARE #result_Cursor as cursor
BEGIN
SET #query = 'Select '+ #firstAttribute+','+#secondAttribute+' from TBL_TEST_DATA_NEW'
SET #cursor_query =' set #cursor = cursor for ' + #query +' open #cursor;'
PRINT 'CURSOR_QUERY'+#cursor_query
exec sys.sp_executesql
#cursor_query
,N'#cursor cursor output'
,#result_Cursor output
FETCH NEXT FROM result_Cursor INTO #x, #y
But when I am executing this SP it is giving me following error
Msg 16916, Level 16, State 1, Procedure TestSP, Line 33
A cursor with the name 'result_Cursor' does not exist.
Execute Command :
Exec TestSP "Column_1","Column_2"
Can someone tell me why I am getting this error
Please Help..
Thanks
The error is saying that Cursor does not exist. You can't start with "set cursor". Also cursor name is without #.
So try using
declare cursorNameHere cursor for SELECT ...
open cursorNameHere
#result_Cursor is a variable, just change your last line to
FETCH NEXT FROM #result_Cursor INTO #x, #y
see example on sql fiddle demo
change
PRINT 'CURSOR_QUERY'+#cursor_query
to
PRINT 'CURSOR_QUERY '+#cursor_query

Specifying Column Name As A Parameter in SELECT statement?

I need to do something like this, but it always fails with 'Error converting data type varchar to int':
DECLARE #intParam INT
DECLARE #ColName VARCHAR(64)
SET #ColName='intcolumn'
SET #intParam = SELECT #ColName FROM myTable
How do I accomplish something like this? I can see the problem is that the SELECT statement simply returns the column name as a string, but I am not sure how to fix that. I am using SQL Server 2008R2.
You need to use dynamic sql:
build your dynamic SQL query (take a look at #SQL variable in sample below)
use output parameter to get value back from dynamic sql (take a look at #intParam and #intParam_out in sample below)
execute dynamic sql using sp_executesql
DECLARE #intParam INT
DECLARE #ColName VARCHAR(64)
SET #ColName='intcolumn'
DECLARE #SQL NVARCHAR(1000)
SET #SQL = 'SELECT #intParam_out = ' + #ColName + ' FROM myTable'
exec sp_executesql #SQL, N'#intParam_out int OUTPUT', #intParam_out = #intParam OUTPUT
Use Cast:
SET #intParam = SELECT cast(#ColName as int) FROM myTable