2013-04-23 5 views
8

を作成した後、インサートを呼び出す:Table1Table2_Idという名前の列、そしてデータベースを持っている場合「無効な列名」エラーテーブルは、私は、データベース内のいくつかの変更を行いSSMSを使用して、SQLスクリプトを開発しています

USE MyDatabase; 

BEGIN TRANSACTION; 

-- some statements 

PRINT(N'#1'); 

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table1' AND COLUMN_NAME = 'Table2_Id')) 
BEGIN 
    ALTER TABLE [dbo].[Table1] DROP CONSTRAINT [FK_Table1_Table2_Table2_Id]; 
    ALTER TABLE [dbo].[Table1] DROP COLUMN [Table2_Id]; 
    DROP TABLE [dbo].[Table2]; 

    PRINT(N'Table2 was dropped.'); 
END 

PRINT(N'#2'); 

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table2')) 
BEGIN 
    CREATE TABLE [dbo].[Table2] 
    (
     [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
     [Number] INT NOT NULL UNIQUE, 
     [Name] NVARCHAR(200) NOT NULL, 
     [RowVersion] TIMESTAMP NOT NULL 
    ); 
PRINT(N'Table2 was re-created.'); 
    INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N'Default value'); 
PRINT(N'Default value was inserted in Table2.'); 
END 

-- some statements 

COMMIT TRANSACTION; 

2つのテーブル(Table1Table2)とそれらの間の外部キーの関係があります。その場合は、私はする必要があります:

  • 外国キー関係をドロップFK_Table1_Table2_Table2_Id;
  • 外部キー列をドロップTable1.Table2_Id;
  • ドロップTable2;
  • 新しいテーブルスキーマを使用してTable2を再作成します。
  • 一部のデフォルト値をTable2に挿入します。

私はこのスクリプトを実行しようとしている、私はこれらのエラーを取得しています:

メッセージ207、レベル16、状態1、行262無効な列名 'ナンバー'。
メッセージ167、レベル16、状態1、行262無効な列名 '名前'。 SQL Serverが(実際にこれらの列を持っていない)Table2の古いスキーマを使用していますが、どのようにテーブルがちょうど新しいスキーマを作成している場合、これは、可能であるように

が見えますか?

私は間違っていますか?

サーバーバージョンはSQL Server 2012(SP1) - 11.0.3128.0(X64)です。

更新

私はPRINTコールを追加しました(上記のスクリプトを参照)。エラーメッセージを除き、メッセージウィンドウには何もありません。だから、スクリプトは実行されていない...何が起こっているの?

答えて

11

SQL Serverはバッチ全体をコンパイルしようとします。テーブルがすでに存在する場合、それは既存の定義に従ってコンパイルされます。新しい列を参照する文はコンパイルされないため、バッチは決して実行されません。

新しい定義を使用してステートメントを新しいバッチにグループ化する必要があります。 「表がすでに存在する場合 - あなただけGO

USE MyDatabase; 

BEGIN TRANSACTION; 

-- some statements 

PRINT(N'#1'); 

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table1' AND COLUMN_NAME = 'Table2_Id')) 
BEGIN 
    ALTER TABLE [dbo].[Table1] DROP CONSTRAINT [FK_Table1_Table2_Table2_Id]; 
    ALTER TABLE [dbo].[Table1] DROP COLUMN [Table2_Id]; 
    DROP TABLE [dbo].[Table2]; 

    PRINT(N'Table2 was dropped.'); 
END 

GO 

PRINT(N'#2'); 

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table2')) 
BEGIN 
    CREATE TABLE [dbo].[Table2] 
    (
     [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
     [Number] INT NOT NULL UNIQUE, 
     [Name] NVARCHAR(200) NOT NULL, 
     [RowVersion] TIMESTAMP NOT NULL 
    ); 
PRINT(N'Table2 was re-created.'); 
    INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N'Default value'); 
PRINT(N'Default value was inserted in Table2.'); 
END 

COMMIT 

を挿入SSMSでこれを実行している場合はそうでない場合、あなたはこの...子バッチで説明のため

EXEC(N'INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N''Default value'');') 
+0

おかげで問題のある行を実行することができますそれは既存の定義に従ってコンパイルされます " - 私が今まで想像することができない最も愚かではない戦略です...' GO'は良い選択肢ではなく、スクリプトはかなり大きく、スクリプト全体の中で広く使用されているスクリプトの先頭で宣言されています。とにかく、ありがとう、私は回避策について考えます。 – Dennis

+0

@Dennis変数を失いたくない場合は、異なるバッチ(テーブルの作成/削除)を別々のストアドプロシージャに分割し、それらをメインのストアドプロシージャにラップすることをお勧めします。 –

関連する問題