SET NOEXEC如何工作?

时间:2009-02-25 22:18:33

标签: sql sql-server tsql

我有以下代码:

-- start of code
set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on
end

go
-- print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

set noexec off
-- end of code

请注意,数据库中不存在表“tblfoobar”。当我运行此代码时,会出现消息:

Please update your DB to version 5 before running this script.
Msg 208, Level 16, State 1, Line 1
Invalid object name 'tblFooBar'.

我原以为将noexec设置为ON可能不会给消息的“消息208”部分。

然后再次“设置noexec on”编译代码,不执行它。试图将一些东西插入到一个不存在的表中是一个编译时错误 - 我猜。如果是这种情况,那么应该出现关于“缺失对象”的错误。

现在让我告诉你我观察到的奇怪行为。如果我从“ - 打印'虚拟'”行中删除评论

-- start of code
set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on
end
go
print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

并执行代码,我只收到以下消息。

  

在运行此脚本之前,请将您的数据库更新到版本5.

这次没有关于丢失表的消息。

有人可以向我解释一下这种行为吗?感谢。

2 个答案:

答案 0 :(得分:3)

我不会期望在你所做的条件中使用“set noexec”是有效的,但事实上它似乎确实有效。

这种行为似乎与它是一个DDL语句有关。如果使用print语句或简单选择查询替换插入,则脚本将按预期工作。

顺便说一句,如果我想做这样的事情,我会使用以下方法:

    create proc tmproc_foobar as
       CREATE TABLE tblFooBar( name nvarchar(20) )
    go

    if exists ( select 1 from sysobjects where type = 'U' and name = 'tblFooBar' )
         exec tmproc_foobar
    go

    drop proc tmproc_foobar
    go

SQL Server允许您使用不存在的对象创建存储过程,因此您可以创建过程,有条件地执行它,然后删除它。这是我有一个很长的升级脚本的方式,有条件地将任何丢失的对象添加到我的数据库。

你也许可以适应这一点。那么你首先不需要noexec,因为你避免了整个无效对象的问题。

答案 1 :(得分:2)

我检查了上面的代码,它运行正常。它没有为丢失的对象提供任何错误消息。

set noexec off

declare @requiredVersion int
declare @currentVersion int

set @requiredVersion = 5
set @currentVersion = 4

if (@currentVersion < @requiredVersion)
begin
    print 'Please update your DB to version 5 before running this script.'
    set noexec on--> here we are setting NOEXEC on
end

go
-- print 'Dummy'
insert into tblFooBar(name) values ('AAA')
go

set noexec off
-- end of code

由于NOEXEC打开,因此下面的代码将被编译而不会被执行,因此它不会通过任何错误消息。