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?这样的东西不是更简单吗;如果两个人在同一时刻使用同一个脚本会发生什么情况?本例中使用的临时表是按会话使用的,没有人会相互影响。我认为是这样。。。哇!