SQL Statement as parameters - sql

Is it possible to do something like that in SQL?
DECLARE #t Nvarchar(50)
SET #t = 'SELECT * FROM KIN_PHON'
execute #t --??

Use exec:
DECLARE #t Nvarchar(50)
SET #t = 'SELECT * FROM KIN_PHON'
exec (#t)
Or with parameters, sp_executesql:
declare #sql nvarchar(max)
set #sql = 'select * from YourTable where ID = #ID'
execute sp_executesql #sql, N'#ID int', #ID = 42;

Related

Dynamically Creating a table and inserting Rows inside a SP

I am trying to run a Stored Procedure that Inserts into a Table.
I keep getting the Incorrect syntax near 'tbl_1_2'.
It doesn't Insert the data.I am using MSSQL2012
Alter PROCEDURE [dbo].[TT] AS
BEGIN
declare #tbl varchar(100);
set #tbl='tbl_1_2';
declare #sql varchar(100);
DECLARE #ptablename VARCHAR(max) = (#tbl)
set #ptablename=#tbl
SET #sql = 'INSERT INTO ' + #ptablename ;
EXEC (#sql)
select *
from (
values('1','2')
) t1 (c1, c2)
End
See this sample and compare with your code to understand your error.
Create Table Test (ID int, Name sysname)
Go
Declare #TableName sysname = 'Test'
DECLARE #ID int = 1
DECLARE #Name sysname = 'Meysam'
Declare #SQL nVarchar(4000) = 'INSERT #TableName (ID, Name) Values (#ID, N''#Name'')'
Set #SQL = REPLACE(#SQL, '#TableName', #TableName)
Set #SQL = REPLACE(#SQL, '#ID', #ID)
Set #SQL = REPLACE(#SQL, '#Name', #Name)
EXEC (#SQL)
SELECT * FROM Test

How to get dynamic SQL query output into declared variable in SQL Server? [duplicate]

I have a piece of dynamic SQL I need to execute, I then need to store the result into a variable.
I know I can use sp_executesql but can't find clear examples around about how to do this.
If you have OUTPUT parameters you can do
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;
But if you don't, and can not modify the SP:
-- Assuming that your SP return 1 value
create table #temptable (ID int null)
insert into #temptable exec mysp 'Value1', 'Value2'
select * from #temptable
Not pretty, but works.
DECLARE #vi INT
DECLARE #vQuery NVARCHAR(1000)
SET #vQuery = N'SELECT #vi= COUNT(*) FROM <TableName>'
EXEC SP_EXECUTESQL
#Query = #vQuery
, #Params = N'#vi INT OUTPUT'
, #vi = #vi OUTPUT
SELECT #vi
DECLARE #tab AS TABLE (col1 VARCHAR(10), col2 varchar(10))
INSERT into #tab EXECUTE sp_executesql N'
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2'
SELECT * FROM #tab
Return values are generally not used to "return" a result but to return success (0) or an error number (1-65K). The above all seem to indicate that sp_executesql does not return a value, which is not correct. sp_executesql will return 0 for success and any other number for failure.
In the below, #i will return 2727
DECLARE #s NVARCHAR(500)
DECLARE #i INT;
SET #s = 'USE [Blah]; UPDATE STATISTICS [dbo].[TableName] [NonExistantStatisticsName];';
EXEC #i = sys.sp_executesql #s
SELECT #i AS 'Blah'
SSMS will show this
Msg 2727, Level 11, State 1, Line 1
Cannot find index 'NonExistantStaticsName'.
If you want to return more than 1 value use this:
DECLARE #sqlstatement2 NVARCHAR(MAX);
DECLARE #retText NVARCHAR(MAX);
DECLARE #ParmDefinition NVARCHAR(MAX);
DECLARE #retIndex INT = 0;
SELECT #sqlstatement = 'SELECT #retIndexOUT=column1 #retTextOUT=column2 FROM XXX WHERE bla bla';
SET #ParmDefinition = N'#retIndexOUT INT OUTPUT, #retTextOUT NVARCHAR(MAX) OUTPUT';
exec sp_executesql #sqlstatement, #ParmDefinition, #retIndexOUT=#retIndex OUTPUT, #retTextOUT=#retText OUTPUT;
returned values are in #retIndex and #retText
Declare #variable int
Exec #variable = proc_name
DECLARE #ValueTable TABLE
(
Value VARCHAR (100)
)
SELECT #sql = N'SELECT SRS_SizeSetDetails.'+#COLUMN_NAME+' FROM SRS_SizeSetDetails WHERE FSizeID = '''+#FSizeID+''' AND SRS_SizeSetID = '''+#SRS_SizeSetID+'''';
INSERT INTO #ValueTable
EXEC sp_executesql #sql;
SET #Value='';
SET #Value = (SELECT TOP 1 Value FROM #ValueTable)
DELETE FROM #ValueTable
This worked for me:
DECLARE #SQL NVARCHAR(4000)
DECLARE #tbl Table (
Id int,
Account varchar(50),
Amount int
)
-- Lots of code to Create my dynamic sql statement
insert into #tbl EXEC sp_executesql #SQL
select * from #tbl
Here's something you can try
DECLARE #SqlStatement NVARCHAR(MAX) = ''
,#result XML
,#DatabaseName VARCHAR(100)
,#SchemaName VARCHAR(10)
,#ObjectName VARCHAR(200);
SELECT #DatabaseName = 'some database'
,#SchemaName = 'some schema'
,#ObjectName = 'some object (Table/View)'
SET #SqlStatement = '
SELECT #result = CONVERT(XML,
STUFF( ( SELECT *
FROM
(
SELECT TOP(100)
*
FROM ' + QUOTENAME(#DatabaseName) +'.'+ QUOTENAME(#SchemaName) +'.' + QUOTENAME(#ObjectName) + '
) AS A1
FOR XML PATH(''row''), ELEMENTS, ROOT(''recordset'')
), 1, 0, '''')
)
';
EXEC sp_executesql #SqlStatement,N'#result XML OUTPUT', #result = #result OUTPUT;
SELECT DISTINCT
QUOTENAME(r.value('fn:local-name(.)', 'VARCHAR(200)')) AS ColumnName
FROM #result.nodes('//recordset/*/*') AS records(r)
ORDER BY ColumnName
This was a long time ago, so not sure if this is still needed, but you could use ##ROWCOUNT variable to see how many rows were affected with the previous sql statement.
This is helpful when for example you construct a dynamic Update statement and run it with exec. ##ROWCOUNT would show how many rows were updated.
Here is the definition

How to store a query result in a variable

SQL Server stored procedure:
CREATE PROCEDURE [dbo].[CheckTableStatus]
#DatabaseName AS NVARCHAR(50) = 'DBA',
#ProjectID AS NVARCHAR(50) = 'CommandLog'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TableCount as int
SET #Temp = 'DECLARE #cnt as int;'
SET #Temp = #Temp + 'USE '+ #DatabaseName +'; SELECT #cnt=COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_NAME=''' + #ProjectID + ''';'
PRINT #Temp
EXEC sp_executesql #temp
--ASSIGN OUTPUT TO #TableCount
IF #TableCount > 0
-- Do something
END
How do I assign the results of #temp being executed to variable #TableCount?
If your goal is to get the count from #temp, try using an OUTPUT with your dynamic SQL:
EXEC sp_executesql #temp, N'#cnt int OUTPUT', #TableCount OUTPUT
These additions to sp_executesql will output the #cnt value in your dynamic SQL to the #TableCount in your current context.
Use the OUTPUT parameter:
CREATE PROCEDURE [dbo].[CheckTableStatus]
#DatabaseName as nvarchar(50) = 'DBA',
#ProjectID as nvarchar(50) = 'CommandLog'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TableCount as int,#Temp nvarchar(max)='';
-- SET #Temp = 'DECLARE #cnt as int;'
SET #Temp = #Temp + 'USE '+ #DatabaseName +'; SELECT #cnt=COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_NAME=''' +
#ProjectID + ''';'
print #Temp
EXEC sp_executesql #temp,
N'#cnt int out',#TableCount out;
--ASSIGN OUTPUT TO #TableCount
IF #TableCount >0
-- Do something
print #TableCount;
END
But why not use the OBJECT_ID function?
Also your code is prone to SQL-injection.
You can set value as
SET #TableCount = #cnt

Variable in a dynamic query

I have a problem once I want to run the next query:
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
declare #tbl table(tmp varchar(255))
insert into #tbl
exec sp_executesql #query
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
The problem is that if I change the variable #j to a numeric value in the declaration of the #query variable, like this
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = 1'
the query is running successfully, if I left the #j variable there, like this
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
I got an error message:
"Must declare the scalar variable #j."
Why? And how can I solve that my query would work with the variable #j?
in the place of ==== where id = #j'
change like this may it works
Convert(nvarchar(2), #j);
You need to cast the #j variable to string. AS its type is INT you should cast it as
CAST(#j AS VARCHAR(12))
Also, you can pass parameters to dynamic SQL statement when it is executed using sp_executesql. In your case it will be something like this:
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
declare #tbl table(tmp varchar(255))
insert into #tbl
exec sp_executesql #query, N'#j INT', #j = #j
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
In the following line:
exec sp_executesql #query, N'#j INT', #j = #j
#query is your dynamic T-SQL statement
N'#j INT' is declaration of parameters
#j = #j is parameters assignments
sp_executsql documentation
You can use parameters in the sp_executesql statement like this:
CREATE TABLE TempTable (
TempID INT IDENTITY(1,1) NOT NULL,
SomeDescription VARCHAR(255) NOT NULL,
PRIMARY KEY(TempID))
INSERT INTO TempTable (SomeDescription)
VALUES ('Description 1'),
('Description 2'),
('Description 3')
DECLARE #sql NVARCHAR(500) = 'SELECT * FROM TempTable WHERE TempID = #TempVar',
#params NVARCHAR(500) = '#TempVar int',
#j INT = 2;
EXEC sp_executesql #sql, #params, #TempVar = #j;
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id ='+ CAST(#j AS VARCHAR(5))
declare #tbl table(tmp varchar(255))
insert into #tbl
exec (#query)
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
enter code here

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