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 = 'collat​​eral' 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代码

TSQL - 选择内的While循环?

TSQL - 从记录集中动态生成查询

解析 TSQL 选择查询并返回列表达式

使用 TSQL OPENJSON 如何从具有动态键名的 JSON 数组中提取值

如何从 tsql (sql 2005) 中的 utc 日期时间计算本地日期时间?