奇怪,列名无效!

gahade 2007-07-09 10:40:27
--测试代码
if exists(select 1 from sysobjects where name='up_test')
drop proc up_test
GO
create proc up_test
as
select top 10 id,name into #t from sysobjects
alter table #t add test char(1) --使用动态SQL也不行
update #t
set test='1'
select * from #t
drop table #t
GO

exec up_test --执行失败
/*
(所影响的行数为 10 行)

服务器: 消息 207,级别 16,状态 1,过程 up_test,行 5
列名 'test' 无效。
*/

if exists(select 1 from sysobjects where name='up_test')
drop proc up_test
GO
create proc up_test
as
select top 10 id,name,'0' as test into #t from sysobjects --这样改就正确
--alter table #t add test char(1)
update #t
set test='1'
select * from #t
drop table #t
GO

exec up_test --执行成功

--是不是存储过程中不能alter临时表呢?但这个字段确实是加进去了.可以select出来,就是不能update.
...全文
324 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
zjcxc 2007-07-09
  • 打赏
  • 举报
回复
简单地说, 楼主应该知道如何看执行计划的啦?


create table #(id int)
alter table # add col int
exec('update # set col = 1')
drop table #

对于上面的语句 , 按 Ctrl + L 看到的执行计划是什么?
对于 EXEC 的那句, 你看不到它里面的执行计划是什么吧? 这是因为 EXEC 里面的执行, 是执行到那一句的时候, 再根据EXEC 的内容去生成执行计划的.
而 EXEC 的语句, 按 Ctrl + L 的时候, 你都可以看到语句是怎么执行的

所以为什么放在 EXEC 中做 UPDATE 能成功, 而在外面不能成功的原因就很明显啦
放在外面的时候, T-SQL 执行前的计划根本就生成不了, 计划都生成不了, 那来执行啊, 所以照楼主的第1种方法, 报错是在生成执行计划的时候, 而不是在执行开始的时候
而 UPDATE 放在 EXEC 中的时候, 执行计划生成肯定没有问题, 所以会顺利执行到 EXEC , 这时候去生成 EXEC 中语句的执行计划, 当然是没有问题的, 因为这时候已经有列了, 那接下来的一系列处理也当然没有问题了

gahade 2007-07-09
  • 打赏
  • 举报
回复
zjcxc(邹建) ( ) 信誉:673 Blog 加为好友 2007-07-09 10:48:09 得分: 0


sql 的执行是先做执行计划, 做执行计划的时候, 没有发生 alter 的操作, 当然就没有这个列, 没有这个列, 做执行计划当然报错啦.

--------------------------------------------------
多谢老大也来捧场~!
小弟愚笨,这句话没理解透.
发生错误是在update处,那也就是update的时候没有发生alter操作,但是如果把alter改成动态SQL就可以.而且alter后select是有这个字段的,实在不知道SQL是怎么处理的!!
gahade 2007-07-09
  • 打赏
  • 举报
回复
谢谢各位!

之前我写的动态SQL有问题,所以报错.
试了下wang的可以.

但是不明白就是alter table ...执行后,select 是可以输出这个列的.为个么不能update呢?
昵称被占用了 2007-07-09
  • 打赏
  • 举报
回复
这样可以
create proc up_test
as
select top 10 id,name into #t from sysobjects
alter table #t add test char(1) --使用动态SQL也不行
exec('
update #t
set test=''1''
')

select * from #t
drop table #t
GO
zjcxc 2007-07-09
  • 打赏
  • 举报
回复
使用动态 T-SQL 的话, 你应该只把后面的 UPDATE 放进去, 这样 UPDATE 因为在 EXEC 中, 会在 ALTER 完成之后做执行计划, 这时就可以了
zjcxc 2007-07-09
  • 打赏
  • 举报
回复
应该用第2种方法处理, 如果要定义列的类型, 可以用:

convert(char(1), '0') as test
zjcxc 2007-07-09
  • 打赏
  • 举报
回复
sql 的执行是先做执行计划, 做执行计划的时候, 没有发生 alter 的操作, 当然就没有这个列, 没有这个列, 做执行计划当然报错啦.
OracleRoob 2007-07-09
  • 打赏
  • 举报
回复
动态SQL当然可以。

--测试代码
if exists(select 1 from sysobjects where name='up_test')
drop proc up_test
GO
create proc up_test
as
select top 10 id,name into #t from sysobjects
--alter table #t add test char(1) --使用动态SQL也不行

exec ('alter table #t add test char(1)')
update #t
set test='1'
select * from #t
drop table #t
GO

exec up_test

22,301

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧