Performing Calculation on dynamic sql - sql

Why does the following error out? It seems the SQL server doesn't recognize - operator on dynamic sql
DECLARE #value INT;
SELECT #value = 10;
EXEC ('SELECT ' + #value -1 );

Nope. You should set up the statement before running it. I would recommend:
DECLARE #value INT;
DECLARE #sql NVARCHAR(MAX);
SET #SQL = 'SELECT #value - 1';
SELECT #value = 10;
EXEC sp_executesql #sql, N'#value int', #value = #value ;
This uses parameters and so is a much more sensible way to run the query.

This works:
DECLARE #value INT;
SELECT #value = 10;
EXEC ('SELECT ' + #value +' -1 ');

Related

Execute dynamic query only to get affected row count

I want to execute a dynamic query to get the affected row count. But SQL Result pane returns me the result after executing it. How to avoid returning the columns. I tried the below way.
DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12'
DECLARE #Count AS INT
EXEC sp_executesql #Command, N'#C INT OUTPUT', #C=#Count OUTPUT
IF (#Count > 0)
BEGIN
EXECUTE (#Command)
END
ELSE
BEGIN
DECLARE #CatalogProduct VARCHAR(MAX) = 'SELECT p.ManufactureCode,p.PartNo,p.Size,p.ID AS ProductID,p.Name ,p.ParentProductID,p.BasePrice FROM Product.Product p WHERE p.ThruDate > GETDATE() '+#Where
EXECUTE (#CatalogProduct)
END
END
I want to avoid returning the null column set from the above attached image.
You can turn off the display, but I think a better approach is to get the count you want directly:
DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12';
DECLARE #count AS INT;
DECLARE #CntCommand NVARCHAR(MAX);
SET #CntCommand = 'SELECT #count = COUNT(*) FROM (' + #Command + ') x)';
EXEC sp_executesql #CntCommand, N'#count INT OUTPUT', #count=#count OUTPUT;
Why not simply?
IF (SELECT COUNT(*) FROM Product = 12) > 0 BEGIN...
I can't see why the COUNT statement needs to be dynamic; there's nothing dynamic about it.
Also, having the SQL '... WHERE p.ThruDate > GETDATE() '+#Where is a terrible idea. If #where is a parameter it'll be wide open to SQL injection.
Try this one. Returns number of rows affected by the last query:
select ##Rowcount
DECLARE #Command NVARCHAR(MAX)= 'SELECT * FROM Product WHERE ID = 12'
DECLARE #CountCommand NVARCHAR(MAX)= 'SELECT #Count=count(1) FROM Product WHERE ID = 12'
DECLARE #Count AS INT
EXEC sp_executesql #CountCommand , N'#Count INT OUTPUT', #Count=#Count OUTPUT
IF (#Count > 0)
BEGIN
EXECUTE (#Command)
END
ELSE
BEGIN
DECLARE #CatalogProduct VARCHAR(MAX) = 'SELECT p.ManufactureCode,p.PartNo,p.Size,p.ID AS ProductID,p.Name ,p.ParentProductID,p.BasePrice FROM Product.Product p WHERE p.ThruDate > GETDATE() '+#Where
EXECUTE (#CatalogProduct)
END
END

How to store values from a dynamic sql into a variable?

I am trying to store next value for the sequence into a variable and the statement is called in a dynamic sql as below.
DECLARE #Sequence VARCHAR(100) = 'IMEIIDLookUP'
DECLARE #NextVal INT
DECLARE #SQL NVARCHAR(4000)
SELECT #SQL = 'SELECT (NEXT VALUE FOR [dbo].' + QUOTENAME(#Sequence) + ')'
SELECT #NextVal = EXEC (#SQL)
SELECT #NextVal
The above query fails with error
Incorrect syntax near the keyword 'EXEC'.
What would be the correct syntax here? Having said that, I cannot avoid using dynamic sql.
Use sp_executesql:
DECLARE #Sequence VARCHAR(100) = 'IMEIIDLookUP';
DECLARE #NextVal INT;
DECLARE #SQL NVARCHAR(4000);
SELECT #SQL = 'SELECT #NextVal = (NEXT VALUE FOR [dbo].' + QUOTENAME(#Sequence) + ')';
exec sp_executesql #SQL, N'#NextVal int output', #NextVal = #NextVal output;
SELECT #NextVal;

SP_ExecuteSQL with Parameters doesn't like Contains clause

I've been tasked with modifying a stored procedure so that it goes from looking like this:
DECLARE #ID nvarchar(10)
SET #ID = '0000000001'
DECLARE #SQL nvarchar(200)
SET #SQL = 'SELECT AppN FROM Apps WHERE CONTAINS(ID, ''"*'' + #ID + ''*"'')'
EXECUTE SP_EXECUTESQL #SQL
to using the parameter list for SP_EXECUTESQL and not string concatenation. The issue is that the following doesn't appear to work:
DECLARE #CID nvarchar(10)
SET #CID = '0000000001'
DECLARE #ID2 nvarchar(14)
SET #ID2 = '"*' + #ID + '*"'
DECLARE #SQL nvarchar(200)
SET #SQL = 'SELECT AppN FROM Apps WHERE CONTAINS(ID, ID2)'
DECLARE #ParamDefinition NCHAR(300)
SET #ParamDefinition = '#ID2 nvarchar(10)'
EXECUTE SP_EXECUTESQL #SQL, #ParamDefinition, #ID2
For whatever reason, the first set of statements works fine. The second does not. I get the following error message: Syntax error near '"' in the full-text search condition '"*00000000'.
If I remove 4 characters from #ID the second set of statements also works. Clearly it has something to do with the length of either #ID or the column ID but I can't figure out what.
You define #ID2 as nvarchar(10) in your parameters for the dynamic SQL.
It's actually 14 characters, so you are cutting off the end of it.
This outputs the correct variable for me:
DECLARE #CID nvarchar(10)
SET #CID = '0000000001'
DECLARE #ID2 nvarchar(14)
SET #ID2 = '"*' + #CID + '*"'
DECLARE #SQL nvarchar(200)
SET #SQL = 'SELECT #ID2'
DECLARE #ParamDefinition NCHAR(300)
SET #ParamDefinition = '#ID2 nvarchar(14)'
EXECUTE SP_EXECUTESQL #SQL, #ParamDefinition, #ID2

Assign variable the result of a select statement

How would you assign a variable the result of a SELECT in Sql Server?
Here is my attempt:
CREATE PROCEDURE x
AS
BEGIN
DECLARE #MyVar integer
DECLARE #sql nvarchar(150), #v nvarchar(50)
Set #v = 'mytable'
--SET #sql = 'SELECT INTO ' + #MyVar + 'count(*) FROM ' + #v
SET #sql = 'Set ' + #MyVar + '= SELECT count(*) FROM ' + #v
EXEC sp_executesql #sql
print #MyVar
END
Conversion failed when converting the varchar value 'Set ' to data
type int.
Any recommendation on learning the syntax would be useful too. Thank you!
You can use an OUTPUT parameter to sp_executesql as below.
DECLARE #MyVar INTEGER
DECLARE #sql NVARCHAR(MAX),
#v SYSNAME
SET #v = N'mytable'
SET #sql = N'SELECT #MyVar = count(*) FROM ' + QUOTENAME(#v)
EXEC sp_executesql
#sql,
N'#MyVar INT OUTPUT',
#MyVar = #MyVar OUTPUT
PRINT #MyVar
RE: "Recommendation on learning the syntax" I don't really have one other than books online but you should read The Curse and Blessings of Dynamic SQL to see why QUOTENAME is important.

Dynamic sql statement to update a variable

my sql statement is something like this below
DECLARE #OLD_NAV_VALUE AS INT
DECLARE #FINAL AS INT
SELECT #OLD_NAV_VALUE = [col1] from TBL_BA where DATE = #id_Date
SET #FINAL = #OLD_NAV_VALUE * 50
But the problem i am haveing here is that the column name in the select statement which is given as [col1] is a dynamic value. So i am trying something like this below.
DECLARE #OLD_NAV_VALUE AS INT
DECLARE #FINAL AS INT
EXEC('SELECT #OLD_NAV_VALUE = [' + #DYNAMIC_COL_NAME + '] from TBL_BA where DATE = ' + #id_Date)
SET #FINAL = #OLD_NAV_VALUE * 50
this gives an error that #OLD_NAV_VALUE has to be declared. So i tried declaring #OLD_NAV_VALUE inside the EXEC statement. But if i do this i am not able to use the same outside the EXEC statement.
Please let me know how to do this.
You can also use the sp_executesql statement with an output parameter:
declare #field nvarchar(50);
set #field = N'FieldToSelect';
declare #sql nvarchar(3000);
declare #parmDefinition nvarchar(500);
SET #parmDefinition = N'#returnValueOUT nvarchar(50) OUTPUT';
set #sql = N'SELECT #ReturnValueOUT = ' + #Field + ' FROM [TableName] WHERE [SomeCondition]'
declare #returnValue nvarchar(50);
EXECUTE sp_executesql #sql, #parmDefinition, #returnValueOut = #returnValue OUTPUT;
SELECT #returnValue
First, I'd suggest that you do a Google on "Erland dynamic SQL" and read his white paper on the subject.
Your design is probably not the best if it requires that you use a dynamic column name like this.
The reason that you can't do what you're trying to do is that everything in the EXEC is entirely in its own scope. If you absolutely have to do it this way though then you could use a table (either a normal table, or a global temporary table) to store the value for use outside of the EXEC.
We've used sp_executesql. Here's another example of a parameterized record count:
DECLARE #sql AS nvarchar(MAX)
SET #sql = N'SELECT #RecordCount = COUNT(*) FROM [{#SchemaName}].[{#TableName}]'
SET #sql = REPLACE(#sql, '{#SchemaName}', #SchemaName)
SET #sql = REPLACE(#sql, '{#TableName}', #TableName)
DECLARE #RecordCount AS int
EXEC sp_executesql
#query = #sql,
#params = N'#RecordCount INT OUTPUT',
#RecordCount = #RecordCount OUTPUT
This worked for me.
I declared a temp table and used it to receive the values from the select statement.
Something like below.
declare #i int
declare #v int
create table #t (val int)
insert into #t
exec ('declare #i int set #i = 0 select #i+1')
select * from #t