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
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
I want to insert multiple csv file to sqlserver table. I have a procedure for doing that. It works but my all files have same column name. So instead of importing all records it just imports column name which is the first row. If I manually delete first row then it imports the other records, I have thousands of files so I cant work manually. I am posting store procedure here. Please tell me if I can change something to make this work.
ALTER procedure [dbo].[usp_ImportMultipleFiles] #filepath varchar(500),
#pattern varchar(100), #TableName varchar(128)
as
set quoted_identifier off
declare #query varchar(1000)
declare #max1 int
declare #count1 int
Declare #filename varchar(100)
set #count1 =0
create table #x (name varchar(200))
set #query ='master.dbo.xp_cmdshell "dir '+#filepath+#pattern +' /b"'
insert #x exec (#query)
delete from #x where name is NULL
select identity(int,1,1) as ID, name into #y from #x
drop table #x
set #max1 = (select max(ID) from #y)
--print #max1
--print #count1
While #count1 <= #max1
begin
set #count1=#count1+1
set #filename = (select name from #y where [id] = #count1)
set #Query ='BULK INSERT '+ #Tablename + ' FROM '''+ #Filepath+#Filename+'''
WITH ( FIELDTERMINATOR = '','',ROWTERMINATOR = ''\n'')'
--print #query
exec (#query)
insert into logtable (query) select #query
end
drop table #y
You can use the First Row option in your bulk insert statement something like...
BULK INSERT Table_Name
FROM 'C:\FilePath'
WITH
(
FIELDTERMINATOR = ','
,ROWTERMINATOR = '\n'
,FIRSTROW = 2 --<-- This option here
)
Edit to your proc
DECLARE #Query NVARCHAR(MAX);
SET #Query = N'BULK INSERT '+ #Tablename +
N' FROM '''+ #Filepath+#Filename +
N''' WITH ( FIELDTERMINATOR = '',''
,ROWTERMINATOR = ''\n''
,FIRSTROW = 2
)'
I build a sql query as:
declare #query1 varchar(1000)
declare #results varchar(4000)
set #results = ''
WHILE (condition)
BEGIN
set #query1 = 'SELECT column FROM table'
set #results = #results + ", " + (select #query1)
END
print #results
So, for example after 2 iterations, I would like to have:
columnvalue, columnvalue
However, in the above code, #results holds the actual sql query instead.
You never execute query1, but istead assign it the text-string SELECT COLUMN FROM table.
What you're looking for is something like SELECT #query1 = column from table
OK. this is how it's done:
declare #query1 nvarchar(1000)
declare #results nvarchar(4000)
set #results = ''
declare #changesOUT nvarchar(1000)
set #query1 = 'SELECT #changes = column FROM table WHERE condition'
EXEC sp_executesql #query1, N'#changes varchar(4000) OUTPUT', #changes=#changesOUT OUTPUT
set #results = #results + (SELECT #changesOUT) + char(10)
print #results
declare #query1 varchar(1000)
declare #results varchar(4000)
set #results = ''
IF OBJECT_ID('tempdb..#ResultSet') IS NOT NULL
BEGIN
DROP TABLE #ResultSet;
END
CREATE TABLE #ResultSet (mycolumn VARCHAR(1000))
WHILE (condition)
BEGIN
set #query1 = 'SELECT column FROM table'
INSERT INTO #ResultSet // Temp table to store result of running dynamic query
exec (#query1) // Exec to run dynamic query
SELECT #query1 = mycolumn FROM #ResultSet
set #results = #results + ', ' + (select #query1)
END
print #results
drop table #ResultSet
Hope this helps.
Can I use the following syntax in stored procedure,
set #count = (select count(*) from [dbo].[employee] where #column_name ='T')
CREATE PROCEDURE Proc_Name
#Column_Name NVARCHAR(128),
#COUNT INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'SELECT #count = count(*) from [dbo].[employee] where ' + QUOTENAME(#Column_Name)
+ N' =''T'''
EXECUTE sp_executesql #Sql
,N'#COUNT INT OUTPUT'
,#COUNT OUTPUT
END