SET NOEXEC如何工作?

ahm*_*mjt 7 sql t-sql sql-server

我有以下代码:

-- 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
Run Code Online (Sandbox Code Playgroud)

请注意,数据库中不存在表"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可能不会给消息中的"Msg 208"部分.

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

现在让我告诉你我观察到的奇怪行为.如果我删除" - ''dummy'"行中的注释

-- 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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Mik*_*keW 4

我没想到在像您所做的那样在条件中使用“set noexec”是有效的,但事实上它似乎确实是有效的。

该行为似乎与它是 DDL 语句这一事实有关。如果将插入替换为打印语句或简单的选择查询,则脚本将按预期工作。

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

    创建 proc tmproc_foobar 为
       创建表 tblFooBar( 名称 nvarchar(20) )
    去

    如果存在(从 sysobjects 中选择 1,其中 type = 'U' 且 name = 'tblFooBar' )
         执行 tmproc_foobar
    去

    删除进程 tmproc_foobar
    去

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

也许你可以调整这一点。那么你一开始就不需要 noexec,因为你避免了无效对象的整个问题。