26

SQL Server のこのコードの何が問題なのか、誰かわかりますか?

IF NOT EXISTS(SELECT *
              FROM   sys.columns
              WHERE  Name = 'OPT_LOCK'
                     AND object_ID = Object_id('REP_DSGN_SEC_GRP_LNK'))
  BEGIN
      ALTER TABLE REP_DSGN_SEC_GRP_LNK
        ADD OPT_LOCK NUMERIC(10, 0)

      UPDATE REP_DSGN_SEC_GRP_LNK
      SET    OPT_LOCK = 0

      ALTER TABLE REP_DSGN_SEC_GRP_LNK
        ALTER COLUMN OPT_LOCK NUMERIC(10, 0) NOT NULL
  END; 

これを実行すると、次のようになります。

メッセージ 207、レベル 16、状態 1、行 3
列名 'OPT_LOCK' が無効です。

更新コマンドで。

ありがとう。

4

3 に答える 3

44

この場合、ここでの私の答えに従って、NOT NULL 1つのステートメントに列を追加し、既存の行の値を設定することで、問題を回避できます。

より一般的には、問題は解析/コンパイルの問題です。SQL Serverは、ステートメントを実行する前に、バッチ内のすべてのステートメントをコンパイルしようとします。

ステートメントがまったく存在しないテーブルを参照している場合、そのステートメントは遅延コンパイルの対象になります。テーブルがすでに存在する場合、存在しない列を参照するとエラーがスローされます。これを回避する最善の方法は、DMLとは異なるバッチでDDLを実行することです。

ステートメントが既存のテーブルの存在しない列と存在しないテーブルの両方を参照している場合、コンパイルが延期される前にエラーがスローされる場合とスローされない場合があります。

個別のバッチで送信するか(たとえば、クライアントツールのバッチセパレータを使用して)、またはGOを使用して個別にコンパイルされた子スコープで実行できます。EXECEXEC sp_executesql

IF ...最初のアプローチでは、バッチにまたがることができないため、コードをリファクタリングする必要があります。

IF NOT EXISTS(SELECT *
              FROM   sys.columns
              WHERE  Name = 'OPT_LOCK'
                     AND object_ID = Object_id('REP_DSGN_SEC_GRP_LNK'))
  BEGIN
      ALTER TABLE REP_DSGN_SEC_GRP_LNK
        ADD OPT_LOCK NUMERIC(10, 0)

      EXEC('UPDATE REP_DSGN_SEC_GRP_LNK SET OPT_LOCK = 0');

      ALTER TABLE REP_DSGN_SEC_GRP_LNK
        ALTER COLUMN OPT_LOCK NUMERIC(10, 0) NOT NULL
  END; 
于 2012-09-21T17:40:22.123 に答える
0

IF NOT EXISTS参考までに、をCOL_LENGTH関数に置き換えることができます。2 つのパラメーターが必要です。

  1. テーブル名と

  2. お探しのコラム

列が見つかった場合は、列のデータ型の範囲を返します。例: Int (4 バイト)。見つからない場合は、NULL.

したがって、これを次のように使用して、3 つのステートメントを 1 つに結合することもできます。

IF (SELECT COL_LENGTH('REP_DSGN_SEC_GRP_LNK','OPT_LOCK')) IS NULL

BEGIN

    ALTER TABLE REP_DSGN_SEC_GRP_LNK
    ADD OPT_LOCK NUMERIC(10, 0) NOT NULL DEFAULT 0

END;

よりシンプルにします。

于 2012-09-21T19:12:42.600 に答える