TSQL 从动态 sql 中选择到 Temp 表
Posted
技术标签:
【中文标题】TSQL 从动态 sql 中选择到 Temp 表【英文标题】:TSQL select into Temp table from dynamic sql 【发布时间】:2012-03-21 01:20:57 【问题描述】:这看起来比较简单,但显然不是。
我需要通过 select into 语法基于现有表创建一个临时表:
SELECT * INTO #TEMPTABLE FROM EXISTING_TABLE
问题是,现有的表名是通过参数接受的...
我可以通过以下方式获取表格的数据:
execute ('SELECT * FROM ' + @tableName)
但是我如何将两者结合起来,以便我可以将执行结果直接放入临时表中。
这将用于的每个表的列都不相同,因此在获取数据之前构建临时表是不切实际的。
我愿意接受任何建议,除了使用全局临时表。
更新:
这完全荒谬,但我对全局临时表的保留意见是,这是一个多用户平台,如果该表会长时间逗留,就会出现问题......
Sooo.. 只是为了完成这一部分,我已经开始使用执行来生成全局临时表。
execute('select * into ##globalDynamicFormTable from ' + @tsFormTable)
然后我使用全局临时表来加载本地临时表:
select * into #tempTable from ##globalDynamicFormTable
然后我删除全局表。
drop table ##globalDynamicFormTable
这很脏,我不喜欢它,但目前,在我找到更好的解决方案之前,它必须起作用。
最后:
我想没有办法绕过它。
最好的答案似乎是;
在执行命令中创建一个视图,并使用它来加载存储过程中的本地临时表。
在执行命令中创建一个全局临时表,并使用它来加载本地临时表。
话虽如此,我可能会坚持使用全局临时表,因为在我的组织中对创建和删除视图进行了审核,我相信他们会质疑它是否一直都在发生。
谢谢!
【问题讨论】:
您使用的是什么版本的 SQL Server? 【参考方案1】:一个工作示例。
DECLARE @TableName AS VARCHAR(100)
SELECT @TableName = 'YourTableName'
EXECUTE ('SELECT * INTO #TEMP FROM ' + @TableName +'; SELECT * FROM #TEMP;')
具有可访问临时表的第二个解决方案
DECLARE @TableName AS VARCHAR(100)
SELECT @TableName = 'YOUR_TABLE_NAME'
EXECUTE ('CREATE VIEW vTemp AS
SELECT *
FROM ' + @TableName)
SELECT * INTO #TEMP FROM vTemp
--DROP THE VIEW HERE
DROP VIEW vTemp
/*START USING TEMP TABLE
************************/
--EX:
SELECT * FROM #TEMP
--DROP YOUR TEMP TABLE HERE
DROP TABLE #TEMP
【讨论】:
INSERT 后的第二个 SELECT 表示可以查询刚插入#TEMP 表的数据。 但是在执行中创建临时表会使临时表完全超出范围...尝试在执行命令之外从临时表中进行选择...它不起作用。 declare vartablename as varchar(100) select vartablename = 'collateral' execute ('select * into #temp from ' + vartablename) select * from #temp 结果 - 无效的对象名称 '#temp'。 是的,我知道如果您在执行命令之外使用它,则会出现“无效的对象名称”问题。您可以像我一样在执行字符串中查询#TEMP。不确定填写临时表后需要做什么.. 我明白了。它与创建一个全局临时表并从那里加载它几乎相同......我认为这个故事的寓意是......你不能从动态选择中制作一个临时表而不会弄脏你的手. +1 坚持下去并提出可行的答案。【参考方案2】:declare @sql varchar(100);
declare @tablename as varchar(100);
select @tablename = 'your_table_name';
create table #tmp
(col1 int, col2 int, col3 int);
set @sql = 'select aa, bb, cc from ' + @tablename;
insert into #tmp(col1, col2, col3) exec( @sql );
select * from #tmp;
【讨论】:
它有一个错误(需要在@sql 周围加上括号),并且没有创建要从中选择的示例表,但一般方法确实有效。我已经更正了这些问题。【参考方案3】:我是如何在动态 sql 中使用数据透视的(#AccPurch 是在此之前创建的)
DECLARE @sql AS nvarchar(MAX)
declare @Month Nvarchar(1000)
--DROP TABLE #temp
select distinct YYYYMM into #temp from #AccPurch AS ap
SELECT @Month = COALESCE(@Month, '') + '[' + CAST(YYYYMM AS VarChar(8)) + '],' FROM #temp
SELECT @Month= LEFT(@Month,len(@Month)-1)
SET @sql = N'SELECT UserID, '+ @Month + N' into ##final_Donovan_12345 FROM (
Select ap.AccPurch ,
ap.YYYYMM ,
ap.UserID ,
ap.AccountNumber
FROM #AccPurch AS ap
) p
Pivot (SUM(AccPurch) FOR YYYYMM IN ('+@Month+ N')) as pvt'
EXEC sp_executesql @sql
Select * INTO #final From ##final_Donovan_12345
DROP TABLE ##final_Donovan_12345
Select * From #final AS f
【讨论】:
【参考方案4】:DECLARE @count_ser_temp int;
DECLARE @TableName AS VARCHAR(100)
SELECT @TableName = 'TableTemporal'
EXECUTE ('CREATE VIEW vTemp AS
SELECT *
FROM ' + @TableTemporal)
SELECT TOP 1 * INTO #servicios_temp FROM vTemp
DROP VIEW vTemp
-- Contar la cantidad de registros de la tabla temporal
SELECT @count_ser_temp = COUNT(*) FROM #servicios_temp;
-- Recorro los registros de la tabla temporal
WHILE @count_ser_temp > 0
BEGIN
END
END
【讨论】:
【参考方案5】:查看OPENROWSET
,然后执行以下操作:
SELECT * INTO #TEMPTABLE FROM OPENROWSET('SQLNCLI'
, 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'SELECT * FROM ' + @tableName)
【讨论】:
存在使开放行集无法工作的问题,更不用说在 3 种不同的环境中,我必须确保每次部署此解决方案时,它都使用正确的开放行集连接字符串. 这不起作用 - 你不能将变量传递给 OpenRowset以上是关于TSQL 从动态 sql 中选择到 Temp 表的主要内容,如果未能解决你的问题,请参考以下文章
t - sql的阶梯:超越基础水平9:动态t - sql代码