2013-04-23 1 views
8

Я занимаюсь разработкой SQL скрипт, с помощью SSMS, что делает некоторые изменения в базе данных:ошибка «Неверное имя столбца» при вызове вставки после того, как таблица создана

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; 

Если Table1 имеет столбец, названный Table2_Id, то база данных имеет две таблицы (Table1 и Table2) и отношение внешних ключей между ними. В этом случае мне необходимо:

  • отношение внешних ключей FK_Table1_Table2_Table2_Id;
  • сбрасывать колонку иностранного ключа Table1.Table2_Id;
  • drop Table2;
  • повторно создать Table2, используя новую схему таблицы;
  • Вставить некоторое значение по умолчанию в Table2.

Когда я пытаюсь выполнить этот сценарий, я получаю эти ошибки:

Msg 207, Level 16, State 1, Line 262 Недопустимое имя столбца 'Номер'.
Msg 207, уровень 16, состояние 1, строка 262 Недопустимое имя столбца «Имя».

Похоже, SQL Server использует старую схему для Table2 (который на самом деле имеет не эти столбцы), но как это возможно, если таблица только что создали с новой схемой?

Что я делаю неправильно?

Версия сервера - SQL Server 2012 (SP1) - 11.0.3128.0 (X64).

ОБНОВЛЕНИЕ.

Я добавил PRINT звонки (см. Вышеприведенный скрипт). В окне сообщений ничего нет, кроме сообщений об ошибках. Итак, скрипт не выполняется ... Что происходит?

ответ

11

SQL Server пытается скомпилировать всю партию. Если таблица уже существует, она будет компилироваться в соответствии с ранее существующим определением. Операция, ссылающаяся на новые столбцы, не компилируется, поэтому пакет не выполняется.

Вам нужно сгруппировать заявления, используя новое определение, в новую партию. Если вы работаете в этом SSMS просто вставить 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 

В противном случае вы можете запустить обижая линию в детской партии

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

Спасибо за объяснение ... Это - «Если таблица уже существует то он будет компилироваться в соответствии с ранее существовавшим определением »- это самая глупая и не очевидная стратегия, которую я когда-либо мог себе представить.« GO »- не очень хороший вариант, сценарий довольно велик, и есть некоторые переменные, объявленный в верхней части скрипта, который широко используется во всем скрипте. В любом случае, спасибо, я подумаю об обходном пути. – Dennis

+0

@Dennis Если вы не хотите потерять свой переменные, то я предложил бы расколоть различную партию (сбрасывает/создание таблиц) в отдельные хранимые процедуры, а затем упаковочные те в основной хранимую процедуре. –

Смежные вопросы