创建具有动态列数的临时表

时间:2015-10-19 13:51:27

标签: sql-server tsql

我正在尝试创建一个具有动态列数的临时表:

set @cmd = ' SELECT * into #temp3 from
            (
                select * from sometable
            ) x pivot
            (
                max(buildrate)
                for name in ('+ @columns +')
            ) as y '

execute(@cmd);

select * from #temp3 left join performed in an elegant way... 

我需要在其他处理中使用该表中的内容。

有没有合理的方法可以做到这一点?

3 个答案:

答案 0 :(得分:3)

一种解决方法是使用全局临时表:

SET @cmd = ' SELECT * INTO ##temp3 FROM
            (
                select * from sometable
            ) x pivot
            (
                max(buildrate)
                for name in ('+ @columns +')
            ) as y '

EXECUTE(@cmd);

SELECT *
INTO #temp3
FROM ##temp3;

DROP TABLE ##temp3;

SELECT *
FROM JOIN #temp3 
LEFT ...;

普通的本地临时表不起作用,因为Dynamic SQL会创建新的上下文。该表位于该上下文中,并且在执行代码时将不再存在,因此您无法在Dynamic-SQL外部使用它。

答案 1 :(得分:0)

基于@Ocaso Protal评论,我创建了这个

-- create global temporary table with timestamp to prevent multiple user collision
DECLARE @timestamp NVARCHAR(255) = REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(NVARCHAR(23), GETDATE(), 121),'-',''),' ',''),':',''),'.','')
DECLARE @temp NVARCHAR(255) = '##temp_'+@timestamp
SET @query = 'CREATE TABLE ' + @temp + ' (RowName NVARCHAR(255), ' + @outputQueryColumns + ')'
EXECUTE sp_executesql @query

-- working with temporary table whether in procedure or in dynamic sql

-- delete global temporary table
SET @query = 'DROP TABLE ' + @temp
EXECUTE sp_executesql @query

答案 2 :(得分:0)

我创建此脚本来测试动态临时表。

我根据https://celedonpartners.com/blog/sql-server-how-to-a-create-temp-table-with-dynamic-column-names/中的帖子

希望这会有所帮助。

-- create and populate table
DROP TABLE dbo.sometable
GO

CREATE TABLE dbo.sometable(
    daterate datetime,
    name varchar(100),
    buildrate decimal(10,3),        
)
GO

DECLARE @COUNT INT

SET @COUNT = 0

WHILE @COUNT < 1000
BEGIN

    IF (CAST(RAND() * 2 AS INT) % 2) = 1
    BEGIN
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()), 'Jeff', RAND() * 25.0)    
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Andrew', RAND() * 25.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Mary', RAND() * 25.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Carl', RAND() * 25.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Zack', RAND()  * 25.0)
    END
    ELSE 
    BEGIN
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Jack', RAND()  * 50.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Mag', RAND()  * 50.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Kim', RAND()  * 50.0)
        INSERT INTO dbo.sometable(daterate, name, buildrate) values(DATEADD(DAY, RAND() * -180, GETDATE()),'Suse', RAND()  * 50.0)
    END    
    SET @COUNT = @COUNT + 1
END    
GO


-- execute query with the created table
DECLARE @columns VARCHAR(MAX)
      , @columns_name varchar(max)
      , @sql varchar(max)

IF OBJECT_ID('tempdb..#temp3') != 0
    DROP TABLE #temp3

SELECT 
    @columns = COALESCE(@columns + ', ', '') + '[' + name + '] float'
   ,@columns_name = COALESCE(@columns_name + ', ', '') + '[' + name + ']'
FROM (SELECT DISTINCT NAME FROM sometable) VW
order by name


CREATE TABLE #temp3(   
   daterate varchar(10)       
)

EXEC('alter table #temp3 add ' + @columns)

SET @sql = 'insert into #temp3 
            select * from
            (
                select name, buildrate, right(convert(varchar(10), daterate, 103), 7) as daterate  from sometable
            ) x pivot
            (
                max(buildrate)
                for name in ('+ @columns_name +')
            ) as y '

EXEC(@sql)

SELECT * FROM #temp3