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

Sql server 创建具有动态列数的临时表,sql-server,tsql,Sql Server,Tsql,我正在尝试创建一个具有动态列数的临时表: set @cmd = ' SELECT * into #temp3 from ( select * from sometable ) x pivot ( max(buildrate) for name in ('+ @columns +') ) as y ' ex

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

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... 
我需要在其他处理中使用该表中的内容


有什么合理的方法可以做到这一点吗?

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

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 ...;

普通的本地临时表无法工作,因为动态SQL会创建新的上下文。该表位于该上下文中,在执行代码时将不再存在,因此您不能在动态SQL之外使用它。

基于@Ocaso Protal comment,我创建了此表

-- 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

我创建这个脚本来测试一个动态临时表

我已经基于post在

希望这能有所帮助

-- 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 

指向sommarskog.se的强制性链接:阅读整篇文章以了解动态SQL。如果您使用的是关系数据库,并且直到运行时才知道数据的结构,那么当我提到这一点时,Almout关闭了页面,然后是一些根本性的错误。这正是模式透视要求Microsoft在SQL Server的未来版本中解决此临时表作用域问题的原因。如果多个用户同时调用此过程,该怎么办?当删除temp3时,我们是否会在temp3中插入?只是出于争论的原因:您可以使用真实的表而不是temp3,并且永远不要删除真实的表。要处理多用户情况,只需在该表中添加一个username列,或者删除任何新请求的以前数据。我只是希望我的同事不会采用这种方法。制作类似“temp_uuuu”+MD5getdate?这样的东西不是更简单吗;如果两个人在同一时刻使用同一个脚本会发生什么情况?本例中使用的临时表是按会话使用的,没有人会相互影响。我认为是这样。。。哇!