日期:2014-05-18  浏览次数:20449 次

一个奇怪的临时表问题???
在查询分析器分两次执行下面的语句:
第一次:(第一次当然出错了,因为临时表根本没有c字段)
if   Object_id( 'tempdb.dbo.#TempTable1 ')   is   not   null
drop   table   #TempTable1
select   1   as   a,2   as   b   into   #TempTable1

SELECT     a,b,c from         #TempTable1

第二次:
if   Object_id( 'tempdb.dbo.#TempTable1 ')   is   not   null
drop   table   #TempTable1
select   1   as   a,2   as   b,3   as   c   into   #TempTable1

SELECT     a,b,c from         #TempTable1

奇怪的是这次还是同样的错误,说c字段不存在???为什么啊???????
如果把SELECT     a,b,c from         #TempTable1
改成:SELECT     * from         #TempTable1  
那么就可以正常执行
我不明白的是我明明把临时表删除了,为什么他还是记住我第一次错误的表结构呢???


------解决方案--------------------
第二次:

if Object_id( 'tempdb.dbo.#TempTable1 ') is not null
drop table #TempTable1
select 1 as a,2 as b,3 as c into #TempTable1

SELECT a,b,c from #TempTable1

直接使用高速缓存中的查询执行计划,当然报错。
------解决方案--------------------
查询是首先生成查询计划,然后再查询 步骤: 生成查询执行计划---> 执行查询
因为你第一次查询时已经生成了查询计划,第一次生成的查询执行计划里并没有字段C
当你第二次查询时,(SELECT a,b,c from #TempTable1)直接调用了高速缓存中的查询执行计划,并没有重新生成查询执行计划,这时当然会报错,C字段不存在
查询执行计划都没有,何来查询!!!
------解决方案--------------------
奇怪真奇怪!


因为Sql语句都是批处理的,这个应该都知道的了,加了GO就代表批处理结束,而没有加那么就是所有的语句当成一个批处理

那么我们来分析一下
第二次:

if Object_id( 'tempdb.dbo.#TempTable1 ') is not null
drop table #TempTable1
select 1 as a,2 as b,3 as c into #TempTable1

SELECT a,b,c from #TempTable1


这三条语句其实是一起执行的,那么 drop table #TempTable1 以后其实还没有提交到,只是在一个隐式的事务中,接着 select into 也能通过,因为它认为这以及是一个新表了,虽然名字一样但是ID是不一样的,

注意: ID 是不一样的


最后一个 SELECT 在执行前有一个编译的过程,其实每条语句执行前都会编译的时候,那么它发现其实上一个 #TempTable1 还在因为还没提交,所以编译这句话的时候就会报错

注意:是执行前编译报的错,并不是执行报的错