2013-04-23 11 views
8

sto sviluppando script SQL, utilizzando SQL Server Management Studio, che apporta alcune modifiche nel database:errore "non valido nome di colonna" quando si chiama inserto dopo la tabella creata

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; 

Se Table1 ha una colonna, di nome Table2_Id, poi di database ha due tabelle (Table1 e Table2) e una relazione di chiave esterna tra di loro. In quel caso, ho bisogno di:

  • goccia relazione di chiave esterna FK_Table1_Table2_Table2_Id;
  • drop chiave esterna chiave Table1.Table2_Id;
  • calo Table2;
  • ricreare Table2, utilizzando il nuovo schema di tabella;
  • inserire un valore predefinito in Table2.

Quando sto cercando di eseguire questo script, sto ottenendo questi errori:

Msg 207, livello 16, stato 1, riga 262 nome di colonna non valido 'Numero'.
Msg 207, livello 16, stato 1, riga 262 Nome colonna non valido "Nome".

Sembra che SQL Server utilizza vecchio schema per Table2 (che ha in effetti non queste colonne), ma come è possibile, se la tabella ha appena creato con il nuovo schema?

Cosa sto sbagliando?

La versione server è SQL Server 2012 (SP1) - 11.0.3128.0 (X64).

UPDATE.

Ho aggiunto le chiamate PRINT (vedere lo script sopra). Non c'è niente nella finestra del messaggio, tranne i messaggi di errore. Quindi, lo script non viene eseguito ... Cosa sta succedendo ??

risposta

11

SQL Server tenta di compilare l'intero batch. Se la tabella esiste già, verrà compilata in base alla definizione preesistente. L'istruzione che fa riferimento alle nuove colonne non viene compilata e pertanto il batch non viene mai eseguito.

È necessario raggruppare le istruzioni utilizzando la nuova definizione in un nuovo batch. Se si esegue questo in SSMS basta inserire una 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 

altrimenti si potrebbe eseguire la riga incriminata in un batch bambino

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

Grazie per la spiegazione ... Questo - "Se la tabella esiste già poi si compilerà secondo la definizione preesistente "- è una strategia più stupida e non ovvia che io abbia mai potuto immaginare ..." GO "non è una buona opzione, lo script è piuttosto grande e ci sono alcune variabili, dichiarato all'inizio della sceneggiatura, ampiamente usato in tutto lo script. Comunque, grazie, penserò a soluzioni alternative. – Dennis

+0

@Dennis Se non si desidera perdere le variabili, suggerirei di suddividere i diversi batch (eliminazione/creazione di tabelle) in stored procedure separate, quindi avvolgerle in una stored procedure principale. –