0

我有一块看起来有点像这样的 SQL

IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '{FOO}')
BEGIN
  EXECUTE ('CREATE DATABASE {FOO}')
  ALTER DATABASE {FOO} SET AUTO_CLOSE OFF
END

{FOO}在运行时替换为用户可配置数据库的名称。逻辑是如果数据库已经存在,我不想创建它。

如果{FOO}是,tempdb那么当查询运行时我会失败

无法在数据库“tempdb”中设置选项“AUTO_CLOSE”。

我的问题是为什么我会失败? SELECT * FROM sys.databases WHERE name = 'tempdb'返回零结果,所以我的整BEGIN/END对肯定不应该运行?事实上,如果我print在开始和结束之间放置一个语句,我看不到任何输出。

我的猜测是 SQL Server 正在对 SQL 进行某种 linting 以确保我不会乱用 tempdb?我已经通过使用解决了这个问题EXECUTE,但我有点困惑为什么我必须这样做!

4

1 回答 1

3

尝试确保两个命令是分开的并且在动态 SQL 中,然后解析器不会捕获对 tempdb 的更改:

EXEC sp_executesql N'CREATE DATABASE {FOO};';
EXEC sp_executesql N'ALTER DATABASE {FOO} SET AUTO_CLOSE OFF;';

这与您无法执行此操作的原因类似:

IF 1 = 1
BEGIN
  CREATE TABLE #t1(id INT);
END
ELSE
BEGIN
  CREATE TABLE #t1(x NVARCHAR(255));
END

即使你我都知道只有一个#t1 代码路径可以到达,SQL Server 假定这两个路径都可以在运行时到达,因此在解析时会报错。

于 2012-09-04T16:16:08.120 回答