如何执行SELECT*INTO[temp table]FROM[存储过程]?不是FROM[Table]并且没有定义[temp Table]?
选择BusinessLine中的所有数据到tmpBusLine工作正常。
select *
into tmpBusLine
from BusinessLine
我也在尝试同样的方法,但使用返回数据的存储过程并不完全相同。
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
输出消息:
消息156,级别15,状态1,第2行关键字附近的语法不正确“exec”。
我读过几个创建与输出存储过程结构相同的临时表的示例,这很好,但最好不要提供任何列。
嗯,您确实需要创建一个临时表,但它不需要有正确的模式。。。。我创建了一个存储过程,它修改了现有的临时表,使其具有正确的数据类型和顺序(删除所有现有列,添加新列)所需的列:
GO
create procedure #TempTableForSP(@tableId int, @procedureId int)
as
begin
declare @tableName varchar(max) = (select name
from tempdb.sys.tables
where object_id = @tableId
);
declare @tsql nvarchar(max);
declare @tempId nvarchar(max) = newid();
set @tsql = '
declare @drop nvarchar(max) = (select ''alter table tempdb.dbo.' + @tableName
+ ' drop column '' + quotename(c.name) + '';''+ char(10)
from tempdb.sys.columns c
where c.object_id = ' +
cast(@tableId as varchar(max)) + '
for xml path('''')
)
alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
exec sp_executeSQL @drop;
declare @add nvarchar(max) = (
select ''alter table ' + @tableName
+ ' add '' + name
+ '' '' + system_type_name
+ case when d.is_nullable=1 then '' null '' else '''' end
+ char(10)
from sys.dm_exec_describe_first_result_set_for_object('
+ cast(@procedureId as varchar(max)) + ', 0) d
order by column_ordinal
for xml path(''''))
execute sp_executeSQL @add;
alter table ' + @tableName + ' drop column ' + quotename(@tempId) + ' ';
execute sp_executeSQL @tsql;
end
GO
create table #exampleTable (pk int);
declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')
exec #TempTableForSP @tableId, @procedureId;
insert into #exampleTable
exec examplestoredProcedure
请注意,如果sys.dm_exec_descript_first_result_set_for_object无法确定存储过程的结果(例如,如果它使用临时表),则这将不起作用。
如果OPENROWSET给您带来问题,从2012年起还有另一种方法;使用sys.dm_exec_descript_first_result_set_for_object,如下所述:检索存储过程的列名和类型?
首先,创建此存储过程以生成临时表的SQL:
CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
@ProcedureName nvarchar(128),
@TableName nvarchar(128),
@SQL nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('
SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +'' + ','
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID(@ProcedureName),
NULL
);
--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))
SET @SQL = @SQL +')'
要使用该过程,请按以下方式调用它:
DECLARE @SQL NVARCHAR(MAX)
exec dbo.usp_GetStoredProcTableDefinition
@ProcedureName='dbo.usp_YourProcedure',
@TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT
INSERT INTO ##YourGlobalTempTable
EXEC [dbo].usp_YourProcedure
select * from ##YourGlobalTempTable
注意,我使用的是全局临时表。这是因为使用EXEC运行动态SQL会创建自己的会话,因此普通临时表将超出任何后续代码的范围。如果全局临时表有问题,可以使用普通临时表,但任何后续SQL都需要是动态的,也就是说,也可以由EXEC语句执行。
存储过程是否只检索数据或修改数据?如果它仅用于检索,则可以将存储过程转换为函数并使用公共表表达式(CTE),而无需声明它,如下所示:
with temp as (
select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp
然而,需要从CTE中检索的内容只能在一个语句中使用。你不能用temp做。。。并尝试在几行SQL之后使用它。对于更复杂的查询,可以在一个语句中包含多个CTE。
例如
with temp1020 as (
select id from dbo.fnFunctionName(10, 20)
),
temp2030 as (
select id from dbo.fnFunctionName(20, 30)
)
select * from temp1020
where id not in (select id from temp2030)