SQL Server Profiler中显示的无提示异常

时间:2017-06-14 14:27:07

标签: sql-server

以下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 tableinsert 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上进行了测试,得到了相同的结果。

1 个答案:

答案 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所指出的),我认为这个问题得到了回答。