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」が無効です。
updateコマンドで。
ありがとう。
この場合、NOT NULL
として列を追加し、1つのステートメントで既存の行の値を設定することで問題を回避できます ここでの私の回答に従って 。
より一般的には、問題は解析/コンパイルの問題です。 SQL Serverは、ステートメントを実行する前に、バッチ内のすべてのステートメントをコンパイルしようとします。
ステートメントがまったく存在しないテーブルを参照する場合、ステートメントは遅延コンパイルの対象になります。テーブルが既に存在する場合、存在しない列を参照するとエラーがスローされます。これを回避する最良の方法は、DMLとは異なるバッチでDDLを実行することです。
ステートメントが既存のテーブルに存在しない列と存在しないテーブルの両方を参照している場合、コンパイルが延期される前にエラーがスローされる場合とスローされない場合があります。
個別のバッチで送信するか(クライアントツールでバッチセパレータGO
を使用するなど)、EXEC
またはEXEC 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;
エラーの根本的な原因は、SQL Server Management Studioを再起動するまで、新しく追加された列名がsys.syscolumnsおよびsys.columnsテーブルに反映されないことです。
参考までに、IF NOT EXISTS
とともに COL_LENGTH
関数。それは2つのパラメータを取ります、
テーブル名と
検索する列
Columnが見つかった場合は、列のデータ型の範囲を返します。Ex: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;
シンプルにします。