Reputation: 941
I would like to generate sql code using the 'stuff' function based on a table name as a parameter
This works:
declare @sql as nvarchar(max);
select @sql = stuff((SELECT distinct [Site]
FROM [ProcterGamble_analytics].[dbo].DATA_table
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 0, '');
exec(@sql);
and i'm looking to do something like
declare @presql as nvarchar(max), @sql as nvarchar(max), @table as nvarchar(max);
SET @table = 'DATA_table';
select @presql = 'SELECT distinct [Site]
FROM [ProcterGamble_analytics].[dbo].' + @table
select @sql = stuff((@presql
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 0, '');
exec(@sql);
Upvotes: 1
Views: 2576
Reputation: 1270993
Your sql
statement is confused as to what is a string and what is the code that generates the string. I think this will work:
select @sql = 'select stuff((' + @presql + '
FOR XML PATH(''''), TYPE
).value(''.'', ''NVARCHAR(MAX)'')
, 1, 0, '''')';
When you execute @sql
, it should return the value.
Upvotes: 2
Reputation: 14925
I think you are confusing creating XML versus concatenate distinct sites with a delimiter and using the stuff function to replace the first delimiter.
I usually like writing code that can be reusable. I am passing the database, schema, table and column names in as input. I am using SYSNAME as the preferred variable.
Noticed I used a group by instead of distinct. In this example, they are the same. However, group by can sometimes save you time.
Check out the processing instruction command. Dumps the dynamic string to a XML document. Real cool?
--
-- Generate a list in XML
--
-- Pass variables w/input
DECLARE @my_database SYSNAME = 'AdventureWorks2012';
DECLARE @my_schema SYSNAME = 'Production';
DECLARE @my_table SYSNAME = 'Product';
DECLARE @my_column SYSNAME = 'Name';
-- Create the dynamic SQL (xml output_)
DECLARE @sql_stmt1 varchar(max) = '';
SET @sql_stmt1 += 'SELECT [' + @my_column + '] FROM [' +
@my_database + '].[' + @my_schema + '].[' + @my_table + '] ';
SET @sql_stmt1 += 'GROUP BY [' + @my_column + '] ';
SET @sql_stmt1 += 'ORDER BY [' + @my_column + '] ';
SET @sql_stmt1 += 'FOR XML PATH (''''), ROOT('''+ @my_column + 's'')';
-- Cool instruction ?
SELECT @sql_stmt1 as [processing-instruction(TSQL)] FOR XML PATH
-- Show my data
EXEC(@sql_stmt1);
In short, here is the output using the adventure works as a example. Just change the input for your case.
Just in-case you wanted a delimited list, I repeated the code using a derived table D and apply the STUFF() function to the resulting field X.
--
-- Generate a delimited list
--
-- Pass variables w/input
DECLARE @my_database SYSNAME = 'AdventureWorks2012';
DECLARE @my_schema SYSNAME = 'Production';
DECLARE @my_table SYSNAME = 'Product';
DECLARE @my_column SYSNAME = 'Name';
-- Create the dynamic SQL
DECLARE @sql_stmt varchar(max) = '';
SET @sql_stmt += 'SELECT STUFF(X, 1, 1, '''') AS LIST FROM ';
SET @sql_stmt += '( SELECT '','' + [' + @my_column +
'] FROM [' + @my_database + '].[' + @my_schema + '].[' + @my_table + '] ';
SET @sql_stmt += 'GROUP BY [' + @my_column + '] ';
SET @sql_stmt += 'ORDER BY [' + @my_column + '] ';
SET @sql_stmt += 'FOR XML PATH ('''') ) AS DT (X) ';
-- Cool instruction ?
SELECT @sql_stmt as [processing-instruction(TSQL)] FOR XML PATH
-- Show my data
EXEC(@sql_stmt);
I hope this answers your question, if not, please write back.
Upvotes: 1
Reputation: 34784
You don't really need the @presql
portion, just need to double up single quotes so they are handled properly when the dynamic portion is processed:
DECLARE @sql AS NVARCHAR(MAX)
,@table AS NVARCHAR(MAX) = 'DATA_table';
SET @sql = 'stuff(( SELECT distinct [Site]
FROM [ProcterGamble_analytics].[dbo].' + @table + '
FOR XML PATH(''''), TYPE
).value(''.'', ''NVARCHAR(MAX)'')
, 1, 0, '''')';
EXEC(@sql);
A good way to test dynamic SQL is to use PRINT(@sql);
insted of EXEC
to confirm the code that will be executed is what you want it to be.
Upvotes: 1