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

オプション 'AUTO_CLOSE' は、データベース 'tempdb' では設定できません。

私の質問は、なぜこの失敗が発生するのですか? ゼロの結果を返すので、ペアSELECT * FROM sys.databases WHERE name = 'tempdb'全体が実行されるべきではないことは確かですか? BEGIN/END実際、printbegin と end の間にステートメントを挿入しても、何も出力されません。

私の推測では、SQL Server は SQL に対して何らかのリンティングを行って、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 コード パスの 1 つだけに到達することを知っていますが、SQL Server は実行時に両方のパスに到達できると想定し、解析時にエラーを出します。

于 2012-09-04T16:16:08.120 に答える