select into语句与临时表用法

发布时间:2020-03-11编辑:脚本学堂
有关select into语句的用法,select into将存储过程结果集添加到临时表的例子,把存储过程结果集select into到临时表。

如何把结果集存放到临时表?

一,select into语句
1. 使用select into会自动生成临时表,不需要事先创建
 

select * into #temp from sysobjects
select * from #temp

2. 如果当前会话中,已存在同名的临时表
 

select * into #temp from sysobjects

再次运行,则会报错提示:数据库中已存在名为 '%1!' 的对象。
msg 2714, level 16, state 6, line 2
there is already an object named '#temp' in the database.

在使用select into前,先做判断:
 

if object_id('tempdb..#temp') is not null
drop table #temp
select * into #temp from sysobjects
select * from #temp

3. 利用select into生成一个空表
如果要生成一个空的表结构,不包含任何数据,可以给定一个恒不等式如下:
 

select * into #temp from sysobjects where 1=2
select * from #temp

二. insert into语句
1. 使用insert into,需要先手动创建临时表

1.1 保存从select语句中返回的结果集
 

复制代码 代码示例:
create table test_getdate(c1 datetime)
insert into test_getdate select getdate()
select * from test_getdate

1.2 保存从存储过程返回的结果集
 

复制代码 代码示例:
create table #helpuser
(
username nvarchar(128),
rolename nvarchar(128),
loginname nvarchar(128),
defdbname nvarchar(128),
defschemaname nvarchar(128),
userid smallint,
sid smallint
)
insert into #helpuser exec sp_helpuser
select * from #helpuser

1.3 保存从动态语句返回的结果集
 

复制代码 代码示例:
create table test_dbcc
(
traceflag varchar(100),
status tinyint,
global tinyint,
session tinyint
)
insert into test_dbcc exec('dbcc tracestatus')
select * from test_dbcc
 

对于动态sql,或者类似dbcc这种非常规的sql语句,都可以通过这种方式来保存结果集。

2. 不能嵌套使用insert exec语句

2.1 例子,尝试保存sp_help_job的结果集到临时表,发生错误
 

复制代码 代码示例:
create table #jobinfo
(
job_id uniqueidentifier,
originating_server nvarchar(128),
name nvarchar(128),
enabled tinyint,
description nvarchar(512),
start_step_id int,
category nvarchar(128),
owner nvarchar(128),
notify_level_eventlog int,
notify_level_email int,
notify_level_netsend int,
notify_level_page int ,
notify_email_operator nvarchar(128),
notify_netsend_operator nvarchar(128),
notify_page_operator nvarchar(128),
delete_level int,
date_created datetime,
date_modified datetime,
version_number int,
last_run_date int,
last_run_time int,
last_run_outcome int,
next_run_date int,
next_run_time int,
next_run_schedule_id int,
current_execution_status int,
current_execution_step nvarchar(128),
current_retry_attempt int,
has_step int,
has_schedule int,
has_target int,
type int
)
insert into #jobinfo exec msdb..sp_help_job

返回错误信息:insert exec 语句不能嵌套。
msg 8164, level 16, state 1, procedure sp_get_composite_job_info, line 72
an insert exec statement cannot be nested.

展开错误信息中的存储过程:
 

exec sp_helptext sp_get_composite_job_info

其中还有个insert into…exec的嵌套调用,sql server在语法上不支持。
 

insert into @xp_results
execute master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @job_owner, @job_id

2.2 可以用分布式查询来避免这个问题,这种写法在inside sql server 2005中作者提到过
(1) 首先到打开服务器选项ad hoc distributed queries
 

exec sp_configure 'show advanced options',1
reconfigure
go
exec sp_configure 'ad hoc distributed queries',1
reconfigure
go

(2) 通过openrowset连接到本机,运行存储过程,取得结果集
使用windows认证:
 

复制代码 代码示例:
select * into #jobinfo_s1
from openrowset('sqloledb', 'server=(local);trusted_connection=yes','exec msdb.dbo.sp_help_job')
select * from #jobinfo_s1

使用sql server认证:
 

select * into #jobinfo_s2
from openrowset('sqloledb','127.0.0.1';'sa';'sa_password','exec msdb.dbo.sp_help_job')
select * from #jobinfo_s2
 

这样的写法,既免去了手动建表的麻烦,也可以避免insert exec 无法嵌套的问题。几乎所有sql语句都可以使用。
 

--dbcc不能直接运行
select a.* into #t
from openrowset('sqloledb','127.0.0.1';'sa';'sa_password',
'dbcc log(''master'',3)') as a
--可以变通下
select a.* into #t
from openrowset('sqloledb','127.0.0.1';'sa';'sa_password',
'exec(''dbcc log(''''master'''',3)'')') as a