SqlServer中selectinto的⽤法在开发过程中,很多时候要把结果集存放到临时表中,常⽤的⽅法有两种。
⼀. 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 where1=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
sql中delete用法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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。