2013-04-23 5 views
8
erstellt

Ich entwickle SQL-Skript, SSMS, das einige Änderungen in der Datenbank macht:„Ungültige Spaltenname“ Fehler beim Aufruf Einsatz nach Tabelle

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; 

Wenn Table1 eine Spalte hat, mit dem Namen Table2_Id, dann Datenbank hat zwei Tabellen (Table1 und Table2) und eine Fremdschlüsselbeziehung zwischen ihnen. In diesem Fall muss ich:

  • Drop Fremdschlüssel Beziehung FK_Table1_Table2_Table2_Id;
  • Drop-Fremdschlüssel-Spalte Table1.Table2_Id;
  • Tropfen Table2;
  • Erneut erstellen Table2, mit neuen Tabellenschema;
  • einen Standardwert in Table2 einfügen.

Wenn ich versuche, dieses Skript auszuführen, erhalte ich diese Fehler:

Msg 207, Ebene 16, Status 1, Zeile 262 Ungültiger Spaltenname 'Number'.
Nachricht 207, Ebene 16, Status 1, Zeile 262 Ungültiger Spaltenname 'Name'.

Sehen aus wie SQL Server altes Schema für Table2 verwendet (was in der Tat hat nicht diese Spalten), aber wie ist das möglich, wenn die Tabelle mit neuem Schema gerade erstellt hat?

Was mache ich falsch?

Serverversion ist SQL Server 2012 (SP1) - 11.0.3128.0 (X64).

UPDATE.

Ich habe PRINT Aufrufe (siehe Skript oben) hinzugefügt. Es gibt nichts im Nachrichtenfenster, außer Fehlermeldungen. Also, das Skript wird nicht ausgeführt ... Was ist los ??

Antwort

11

SQL Server versucht, den gesamten Stapel zu kompilieren. Wenn die Tabelle bereits existiert, wird sie gemäß der vorher existierenden Definition kompiliert. Die Anweisung, die auf die neuen Spalten verweist, wird nicht kompiliert und daher wird der Batch nie ausgeführt.

Sie müssen die Anweisungen unter Verwendung der neuen Definition in einem neuen Stapel gruppieren. Wenn Sie dies in SSMS ausführen legen Sie einfach ein 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 

Andernfalls könnten Sie die Codezeile in einem Kind Batch

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

Danke für die Erklärung laufen ... Diese - „Wenn die Tabelle bereits vorhanden dann wird es nach der bereits bestehenden Definition kompilieren "- ist eine sehr dumme und nicht offensichtliche Strategie, die ich mir jemals vorstellen konnte ...' GO' ist keine gute Option, das Skript ist ziemlich groß, und es gibt einige Variablen, oben im Skript deklariert, das im gesamten Skript verwendet wird. Wie auch immer, danke, ich werde über eine Problemumgehung nachdenken. – Dennis

+0

@Dennis Wenn Sie Ihre Variablen nicht verlieren möchten, würde ich vorschlagen, die verschiedenen Stapel (Tabellen löschen/erstellen) in separate gespeicherte Prozeduren aufzuteilen und diese dann in eine gespeicherte Hauptprozedur einzufügen. –