从动态SQL中选择并插入到临时表中的T-SQL语句

22

看起来相对简单,但显然并不是。

我需要通过select into语法基于现有表创建一个临时表:

SELECT * INTO #TEMPTABLE FROM EXISTING_TABLE

问题是,现有的表名是通过参数传递的...

我可以通过以下方式获取表格数据:

execute ('SELECT * FROM ' + @tableName)
但是我该如何把这两者结合起来,以便可以直接将execute的结果放入临时表中呢?
每个表的列都不相同,因此在获取数据之前构建临时表并不实际。
我愿意听取任何建议,除了使用全局临时表。
更新:
这完全荒谬,但我对全局临时表的保留意见在于,这是一个多用户平台,如果表会持续存在很长时间,就会出现问题...
所以...为了解决这个问题,我已经开始使用execute来生成全局临时表。
execute('select * into ##globalDynamicFormTable from ' + @tsFormTable) 

然后我使用全局临时表来加载本地临时表:

select * into #tempTable from ##globalDynamicFormTable

然后我删除了全局表。

drop table ##globalDynamicFormTable

这很糟糕,我不喜欢它,但在找到更好的解决方案之前,它将不得不工作。

总之:

我想没有绕过它的方法了。

最好的答案似乎是:

在执行命令中创建一个视图,并使用它来加载存储过程中的本地临时表。

在执行命令中创建一个全局临时表,并使用它来加载本地临时表。

话虽如此,我可能会坚持使用全局临时表,因为在我的组织中,创建和删除视图是需要审计的,如果这种情况经常发生,他们肯定会质疑。

谢谢!


你使用的 SQL Server 版本是哪个? - Raj More
6个回答

27
一个可用的示例。
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

3
但是在执行语句中创建临时表会使临时表完全超出范围...尝试在执行命令之外从临时表中选择...它不会起作用。 - Patrick
是的,我明白如果您在执行命令之外使用它会出现“无效对象名称”的问题。您可以像我一样在执行字符串中查询#TEMP。不确定在填充临时表后您需要做什么。 - Kaf
@RajMore 当然它可以工作,但它不适用于我需要的情况。它使临时表超出范围。正如您可以从我对原始评论的第二个回复中看到的那样。 - Patrick
@Indikaf 我将根据存储过程中的业务流程,从作为字符串发送的值列表中插入值到临时表中,然后使用临时表将其插入回原始表中。 - Patrick
3
我明白了。这基本上与创建全局临时表并从中加载相同...我认为故事的寓意是...你不能从动态选择中制作临时表而不弄脏手。+1坚持下去并提出可行的答案。 - Patrick
显示剩余5条评论

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

1
它出现了一个错误(需要在@sql周围加上括号),并且没有创建样本表以供选择,但是一般的方法确实有效。我已经纠正了这些问题。 - dstandish

0

如何通过动态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

0
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

0
今天我遇到了同样的问题。我不确定执行查询返回了多少列。因此,我创建了一个带有单个列的临时表,并使用动态执行查询进行更改。
我从c-sharpcorner.com得到了这个想法。我使用COALESCE而不是while循环来创建一个单独的逗号分隔列。
如有建议或问题,请随意提出。
-- Temp table you want to access after dynamic insert
drop table if exists #TempTable
create table #TempTable (ID int)

DECLARE @ColNames nvarchar(max), @DynamicSQL nvarchar(max)

-- query to create dynamic columns you need
SELECT @ColNames = COALESCE(@ColNames + ',', '') + QUOTENAME(COLUMN_NAME) + ' NVARCHAR(max) NULL'
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'TABLE_NAME'

-- alter script to add column to temp table
SET @DynamicSQL = 'ALTER TABLE #TempTable ADD ' + @ColNames

-- add dynamic columns to temp table
EXEC (@DynamicSQL)

-- execute the query and result will be in #temptable
insert into #TempTable
execute('select 1 as ID,* from TABLE_NAME') 

select * from #TempTable

-1

看一下OPENROWSET,然后做类似的事情:

SELECT * INTO #TEMPTABLE FROM OPENROWSET('SQLNCLI'
     , 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'SELECT * FROM ' + @tableName)

存在权限问题,导致无法使用open rowset,更不用说在3个不同的环境中,每次部署此解决方案时都必须确保使用正确的连接字符串来打开rowset。 - Patrick
3
无法使用变量传递给OpenRowset,此方法不起作用。 - sianabanana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接