April 9, 2025 at 1:24 pm
I'm trying to dynamically create a temp table, basing the column names on another table. It appears to be working (???) but I can't select or insert any data into the table that was just built?
Here is a test of what I'm trying to do.
IF OBJECT_ID('tempdb..#source_table', 'U') IS NOT NULL DROP TABLE #source_table;
IF OBJECT_ID('tempdb..#new_table', 'U') IS NOT NULL DROP TABLE #new_table;
DECLARE @sql NVARCHAR(MAX);
DECLARE @cols NVARCHAR(MAX);
DECLARE @insert_sql NVARCHAR(MAX);
/* create test table */
CREATE TABLE #source_table (
id INT,
column_name VARCHAR(100),
value INT
);
INSERT INTO #source_table (id, column_name, value) VALUES
(1, 'ColumnA', 10),
(2, 'ColumnB', 20),
(3, 'ColumnA', 30),
(4, 'ColumnC', 40),
(5, 'ColumnB', 50);
/* create a list of column names */
SELECT @cols = STRING_AGG(QUOTENAME(column_name), ' int , ')
FROM (SELECT DISTINCT column_name FROM #source_table) AS cols;
/* create sql to create table */
SET @sql = 'CREATE TABLE #new_table (' + @cols + ' int);';
/* create table */
EXEC sp_executesql @sql;
Insert Into #new_table ([ColumnA], [ColumnB], [ColumnC], [ColumnD]) values (1,2,3,4);
Select * From #new_table;
Can anyone give me some ideas?
Thank you,m
April 9, 2025 at 2:16 pm
This works using a global temporary table:
IF OBJECT_ID('tempdb..#source_table', 'U') IS NOT NULL DROP TABLE #source_table;
IF OBJECT_ID('tempdb..##new_table', 'U') IS NOT NULL DROP TABLE ##new_table;
DECLARE @sql NVARCHAR(MAX);
DECLARE @cols NVARCHAR(MAX);
DECLARE @insert_sql NVARCHAR(MAX);
/* create test table */
CREATE TABLE #source_table (
id INT,
column_name VARCHAR(100),
value INT
);
INSERT INTO #source_table (id, column_name, value) VALUES
(1, 'ColumnA', 10),
(2, 'ColumnB', 20),
(3, 'ColumnA', 30),
(4, 'ColumnC', 40),
(5, 'ColumnB', 50);
/* create a list of column names */
SELECT @cols = STRING_AGG(QUOTENAME(column_name), ' int , ')
FROM (SELECT DISTINCT column_name FROM #source_table) AS cols;
/* create sql to create table */
SET @sql = 'CREATE TABLE ##new_table (' + @cols + ' int);';
/* create table */
EXEC sp_executesql @sql;
Insert Into ##new_table ([ColumnA], [ColumnB], [ColumnC]) values (1,2,3);
Select * From ##new_table;
Or this works where the temporary table is accessed from within the scope of sp_executesql
IF OBJECT_ID('tempdb..#source_table', 'U') IS NOT NULL DROP TABLE #source_table;
DECLARE @sql NVARCHAR(MAX);
DECLARE @cols NVARCHAR(MAX);
DECLARE @insert_sql NVARCHAR(MAX);
/* create test table */
CREATE TABLE #source_table (
id INT,
column_name VARCHAR(100),
value INT
);
INSERT INTO #source_table (id, column_name, value) VALUES
(1, 'ColumnA', 10),
(2, 'ColumnB', 20),
(3, 'ColumnA', 30),
(4, 'ColumnC', 40),
(5, 'ColumnB', 50);
/* create a list of column names */
SELECT @cols = STRING_AGG(QUOTENAME(column_name), ' int , ')
FROM (SELECT DISTINCT column_name FROM #source_table) AS cols;
PRINT 'CREATE TABLE #new_table (' + @cols + ' int);'
/* create sql to create table */
SET @sql = 'CREATE TABLE #new_table (' + @cols + ' int);
Insert Into #new_table ([ColumnA], [ColumnB], [ColumnC]) values (1,2,3);
Select * From #new_table;'
/* create table */
EXEC sp_executesql @sql;
April 9, 2025 at 2:28 pm
if a global temp table works, that would be fantastic. When, how does a global temp table get dropped.
P.S. I'm thinking of putting this code into a report, which can be run on demand.
April 9, 2025 at 2:45 pm
Be careful with global temp tables.
Multiple SPIDs could end up tripping over each other, as they can all see the global temp table.
April 9, 2025 at 2:46 pm
if a global temp table works, that would be fantastic. When, how does a global temp table get dropped.
P.S. I'm thinking of putting this code into a report, which can be run on demand.
Global temporary tables are stored in tempdb, just like local temporary tables. However, unlike local temp tables, they are accessible from any session. A global temp table remains available until it is explicitly dropped or the SQL Server instance is restarted.
April 9, 2025 at 2:46 pm
How could I incorporate this into a report?
Can I add this to the bottom of the query?
IF OBJECT_ID('tempdb..#source_table', 'U') IS NOT NULL DROP TABLE #source_table;
IF OBJECT_ID('tempdb..##new_table', 'U') IS NOT NULL DROP TABLE ##new_table;
April 9, 2025 at 2:47 pm
How could I incorporate this into a report?
Can I add this to the bottom of the query?
IF OBJECT_ID('tempdb..#source_table', 'U') IS NOT NULL DROP TABLE #source_table;
IF OBJECT_ID('tempdb..##new_table', 'U') IS NOT NULL DROP TABLE ##new_table;
In SQL Server 2016 you can write
DROP TABLE IF EXIST #source_table, ##new_table;
But #source_table won't exist if you created with sp_executesql and try to drop it outside the scope of sp_executesql
April 9, 2025 at 3:02 pm
WOW!!!
Thank you, I think this give me a lot to work on. Now my next task is to dynamically load the table with the data without having to manually build this:
INSERT INTO ##new_table ([ColumnA], [ColumnB], [ColumnC])
SELECT
MAX(CASE WHEN column_name = 'ColumnA' THEN value END),
MAX(CASE WHEN column_name = 'ColumnB' THEN value END),
MAX(CASE WHEN column_name = 'ColumnC' THEN value END)
FROM source_table;
What this is really supposed to do is making a dynamic pivot table.
April 9, 2025 at 3:08 pm
What this is really supposed to do is making a dynamic pivot table.
This might be of interest:
https://www.sqlservercentral.com/articles/cross-tabs-and-pivots-part-2-dynamic-cross-tabs
April 9, 2025 at 3:09 pm
Try something like this
if object_id('tempdb..#temp') is not null
drop table #temp;
GO
create table #temp
(
date datetime,
category varchar(3),
amount money
);
insert into #temp(date, category, amount) values ('1/1/2012', 'ABC', 1000.00);
insert into #temp(date, category, amount) values ('2/1/2012', 'DEF', 500.00);
insert into #temp(date, category, amount) values ('2/1/2012', 'GHI', 800.00);
insert into #temp(date, category, amount) values ('2/10/2012', 'DEF', 700.00);
insert into #temp(date, category, amount) values ('3/1/2012', 'ABC', 1100.00);
--select * from #temp;
--=======================================================================
DECLARE
@pvtCols NVARCHAR(MAX)
, @Query NVARCHAR(MAX)
, @Debug BIT = 0; /* Chnage this to 1 to print the SQL for debugging */
SET @pvtCols = STUFF( (SELECT DISTINCT ',' + QUOTENAME(c.category)
FROM #temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
----------------------------
-- Using CROSS-TAB Report --
----------------------------
SET @Query = 'SELECT t.date ';
SELECT @Query += '
, MAX(CASE WHEN t.category = ''' + c.category + ''' THEN t.amount ELSE NULL END) AS ' + QUOTENAME(c.category)
FROM #temp AS c
GROUP BY c.category
ORDER BY c.category;
SET @Query += '
FROM #temp as t
GROUP BY date;';
IF (@Debug = 1) PRINT (@Query);
EXEC sp_executesql @Query;
drop table #temp;
GO
April 9, 2025 at 3:11 pm
Great, I'll give that a read. Fingers crossed.
Thank you for all of your help everyone,
Viewing 12 posts - 1 through 12 (of 12 total)
You must be logged in to reply to this topic. Login to reply
This website stores cookies on your computer.
These cookies are used to improve your website experience and provide more personalized services to you, both on this website and through other media.
To find out more about the cookies we use, see our Privacy Policy