【问题标题】:Customizable database names and TempDB可自定义的数据库名称和 TempDB
【发布时间】:2012-09-05 00:16:08
【问题描述】:

我有一段看起来有点像这样的 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 对肯定不应该运行吗?事实上,如果我在 begin 和 end 之间放置 print 语句,我看不到任何输出。

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

【问题讨论】:

  • 听起来像是解析问题。您的代码当前已损坏 - ALTER 是否在字符串中?如果没有,请尝试将其作为动态字符串的一部分。
  • 抱歉,打错字了,我更正了。更改是字符串的一部分。

标签: sql sql-server sql-server-2008


【解决方案1】:

尝试确保两个命令是独立的并且在动态 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 假定这两个路径都可以在运行时访问,因此在解析时会报错。

【讨论】:

  • 我如何知道是使用动态 SQL 还是只使用文字 SQL?我对解析器的职责感到困惑,因为它似乎在我的代码中发现了语义错误。
  • 对于像这样的事情,你正在参数化在普通 SQL/DDL 中无法参数化的东西,你更安全地使用动态 SQL 恕我直言。
猜你喜欢
  • 2018-06-21
  • 1970-01-01
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多