以下SQL脚本在SQL Server配置文件上产生Invalid object name '#temp'
异常,但 SQL Server Management Studio 和 sqlcmd 都不会引发异常:
create table #temp (id int)
insert into #temp (id) values (1)
我只是通过运行带有事件" Exception"的SQL Server Profiler来捕获它。打开,可以在"事件选择"配置跟踪属性时的选项卡。
由于异常往往会降低服务器的速度,我使用表变量尝试了类似的代码:
declare @temp table (id int)
insert into @temp (id) values (1)
上面的代码不仅避免了异常,而且在重复调用时也更快,这通过使用临时表来改善性能损失:
if (db_id('performance_test') is null)
create database performance_test
go
use performance_test
go
/* --------------------------- */
/* stress test with temp table */
/* --------------------------- */
declare
@i int,
@sql varchar(max),
@start_time datetime,
@end_time datetime
set @i = 0
set @sql = 'create table #temp (id int)' + Char(13) + Char(10) + 'insert into #temp (id) values (1)'
set @start_time = getdate()
while (@i < 10000)
begin
exec (@sql)
set @i = @i + 1
end
set @end_time = getdate()
select [Elapsed milliseconds] = datediff(millisecond, @start_time, @end_time) -- outputs 17090 milliseconds
go
/* ------------------------------- */
/* stress test with table variable */
/* ------------------------------- */
declare
@i int,
@sql varchar(max),
@start_time datetime,
@end_time datetime
set @i = 0
set @sql = 'declare @temp table (id int)' + char(13) + char(10) + 'insert into @temp (id) values (1)'
set @start_time = getdate()
while (@i < 10000)
begin
exec (@sql)
set @i = @i + 1
end
set @end_time = getdate()
select [Elapsed milliseconds] = datediff(millisecond, @start_time, @end_time) -- outputs 10010 milliseconds
我经常读到本地临时表和表变量可以互换使用(当然如果使用单个批处理),但我认为已证实的行为以上可以证明不是。
虽然它有点明显,但值得注意的是,如果我们在不同批次中将create table
与insert into
分开,则不会引发异常:
create table #temp (id int)
go
insert into #temp (id) values (1)
这是无声异常是一个SQL Server的错误,还是可以调用的东西&#34;设计中的一个功能&#34;?考虑到上面的静默异常,也许最好总是使用表变量而不是临时表。
P.S。:我已经在SQL Server 2014和SQL Server 2016 Developer Edition上进行了测试,得到了相同的结果。
答案 0 :(得分:0)
正如@JeroenMostert所指出的,异常"Invalid object name"
可能在批量重新编译中解决(我不知道)。考虑到&#34;延迟名称解析&#34;它是完全合理的。进程,这是SQL Server社区中的已知主题。
下面的第一个链接是我在MSDN上发布的问题,由Mohsin_A_Khan回答,谈论&#34;延迟名称解析&#34; SQL Server中的进程。另外两个链接有助于理解它的实际工作方式:
Getting "Invalid object name" by creating a temp table and inserting rows right away
How to find what caused errors reported in a SQL Server profiler trace?
Deferred Name Resolution and Compilation
由于&#34;无效的对象名称&#34;由于重新编译过程是预期的,并且不应该通过简单地用表变量替换临时表来避免(再次,如@JeroenMostert所指出的),我认为这个问题得到了回答。