Как добавить столбец в TSQL после определенного столбца? - PullRequest
33 голосов
/ 28 октября 2011

У меня есть таблица:

MyTable
    ID
    FieldA
    FieldB

Я хочу изменить таблицу и добавить столбец, чтобы он выглядел так:

MyTable
    ID
    NewField
    FieldA
    FieldB

В MySQL я бы так:

ALTER TABLE MyTable ADD COLUMN NewField int NULL AFTER ID;

Одна строка, красиво, просто, отлично работает. Как мне это сделать в мире Microsoft?

Ответы [ 9 ]

31 голосов
/ 28 октября 2011

К сожалению, вы не можете.

Если вы действительно хотите, чтобы они были в таком порядке, вам придется создать новую таблицу со столбцами в этом порядке и скопировать данные. Или переименовать столбцы и т. Д. Нет простого пути.

6 голосов
/ 06 ноября 2015

решение:

Это будет работать для таблиц, в которых нет изменений в таблице изменений, которые могли бы вызвать каскадные события. Сначала убедитесь, что вы можете отбросить таблицу, которую вы хотите реструктурировать, без каких-либо катастрофических последствий. Запишите все зависимости и ограничения столбцов, связанные с вашей таблицей (т. Е. Триггеры, индексы и т. Д.) .). Возможно, вам придется положить их обратно, когда вы закончите.

ШАГ 1: создайте временную таблицу для хранения всех записей из таблицы, которую вы хотите реструктурировать. Не забудьте включить новый столбец .

CREATE TABLE #tmp_myTable
(   [new_column] [int] NOT NULL, <-- new column has been inserted here!
    [idx] [bigint] NOT NULL,
    [name] [nvarchar](30) NOT NULL,
    [active] [bit] NOT NULL
)

ШАГ 2: Убедитесь, что все записи скопированы и структура столбцов выглядит так, как вы хотите.

SELECT TOP 10 * FROM #tmp_myTable ORDER BY 1 DESC - вы можете сделать COUNT (*) или что-нибудь еще, чтобы убедиться, что вы скопировали все записи

ШАГ 3: УБРАТЬ оригинальную таблицу:

DROP TABLE myTable

Если вы недовольны тем, что могут произойти плохие вещи, просто переименуйте исходную таблицу (вместо того, чтобы бросать ее). Таким образом, его всегда можно вернуть обратно.

EXEC sp_rename myTable, myTable_Copy

ШАГ 4: Создайте таблицу myTable так, как вам нужно (должно совпадать с # tmp_myTable структурой таблицы)

CREATE TABLE myTable
(   [new_column] [int] NOT NULL,
    [idx] [bigint] NOT NULL,
    [name] [nvarchar](30) NOT NULL,
    [active] [bit] NOT NULL
)

- не забывайте, какие ограничения вам могут понадобиться

ШАГ 5: Скопируйте все записи из таблицы temp # tmp_myTable в новую (улучшенную) таблицу myTable .

INSERT INTO myTable ([new_column],[idx],[name],[active])
SELECT [new_column],[idx],[name],[active]
FROM #tmp_myTable

ШАГ 6. Проверьте, вернулись ли все данные в новую улучшенную таблицу myTable . Если да, очистите после себя и УДАЛИТЕ временную таблицу # tmp_myTable и таблицу myTable_Copy , если вы решили переименовать ее вместо ее удаления.

3 голосов
/ 28 октября 2011

Вы сможете сделать это, если создадите столбец с помощью графического интерфейса в Management Studio. Я полагаю, что Management Studio фактически полностью воссоздает таблицу, и именно поэтому это происходит.

Как уже упоминали другие, порядок столбцов в таблице не имеет значения, и если это так, то с вашим кодом что-то не так.

2 голосов
/ 12 сентября 2013

/ * Скрипт для изменения порядка столбцов таблицы
Обратите внимание, что это создаст новую таблицу для замены исходной таблицы
ОДНАКО он не копирует триггеры или другие свойства таблицы - только данные
* /

Создайте новую таблицу со столбцами в требуемом порядке

Select Column2, Column1, Column3 Into NewTable from OldTable

Удалить исходную таблицу

Drop Table OldTable;

Переименовать новую таблицу

EXEC sp_rename 'NewTable', 'OldTable';

1 голос
/ 06 февраля 2015

В SQL Enterprise Management Studio откройте свою таблицу, добавьте столбец в нужное вам место, а затем - вместо сохранения изменения - сгенерируйте сценарий изменения. Вы можете увидеть, как это делается в SQL.

Короче говоря, то, что сказали другие, правильно. Студия SQL Management переносит все ваши данные во временную таблицу, удаляет таблицу, воссоздает ее со столбцами в правильном порядке и помещает туда данные временной таблицы. Не существует простого синтаксиса для добавления столбца в определенной позиции.

1 голос
/ 28 сентября 2013

Даже если вопрос старый, потребуется более точный ответ о Management Studio.

Вы можете создать столбец вручную или с помощью Management Studio. Но Management Studio потребует пересоздания таблицы и приведет к превышению времени ожидания, если у вас уже есть слишком много данных, избегайте, если таблица не легкая.

Чтобы изменить порядок столбцов, вам просто нужно переместить их в Management Studio. Это не должно требовать (исключения, скорее всего, существуют), что Management Studio воссоздает таблицу, поскольку она, скорее всего, изменяет порядок расположения столбцов в определениях таблицы.

Я неоднократно делал это с таблицами, которые не могли добавить столбцы с графическим интерфейсом из-за данных в них. Затем переместили столбцы с помощью графического интерфейса Management Studio и просто сохранили их.

Вы перейдете от гарантированного времени до нескольких секунд ожидания.

1 голос
/ 29 октября 2011

В Microsoft SQL Server Management Studio (инструмент администратора для MSSQL) просто зайдите в «дизайн» таблицы и перетащите столбец на новую позицию. Не командная строка, но вы можете сделать это.

1 голос
/ 28 октября 2011

Вы должны восстановить таблицу.К счастью, порядок столбцов вообще не имеет значения!

Наблюдайте, как я волшебным образом изменяю порядок ваших столбцов:

SELECT ID, Newfield, FieldA, FieldB FROM MyTable

Также об этом спрашивали оБазиллион раз прежде.

0 голосов
/ 27 августа 2014

Это абсолютно возможно. Хотя вы не должны этого делать, если не знаете, с чем имеете дело. У меня ушло около 2 дней, чтобы понять это. Вот хранимая процедура, в которую я вхожу: --- имя базы данных (имя схемы "_" для удобства чтения) --- имя таблицы --- колонка --- тип данных столбца (добавленный столбец всегда нулевой, иначе вы не сможете вставить) --- позиция нового столбца.

Поскольку я работаю с таблицами из инструментария SAM (а некоторые из них имеют> 80 столбцов), типичная переменная не сможет содержать запрос. Это вызывает необходимость внешнего файла. Теперь будьте осторожны, где вы храните этот файл и у кого есть доступ на NTFS и сетевом уровне.

Ура! * * 1005

USE [master]
GO
/****** Object:  StoredProcedure [SP_Set].[TrasferDataAtColumnLevel]    Script Date: 8/27/2014 2:59:30 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [SP_Set].[TrasferDataAtColumnLevel]
(
    @database varchar(100),
    @table varchar(100),
    @column varchar(100),
    @position int,
    @datatype varchar(20)    
)
AS
BEGIN
set nocount on
exec  ('
declare  @oldC varchar(200), @oldCDataType varchar(200), @oldCLen int,@oldCPos int
create table Test ( dummy int)
declare @columns varchar(max) = ''''
declare @columnVars varchar(max) = ''''
declare @columnsDecl varchar(max) = ''''
declare @printVars varchar(max) = ''''

DECLARE MY_CURSOR CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR 
select column_name, data_type, character_maximum_length, ORDINAL_POSITION  from ' + @database + '.INFORMATION_SCHEMA.COLUMNS where table_name = ''' + @table + '''
OPEN MY_CURSOR FETCH NEXT FROM MY_CURSOR INTO @oldC, @oldCDataType, @oldCLen, @oldCPos WHILE @@FETCH_STATUS = 0 BEGIN

if(@oldCPos = ' + @position + ')
begin
    exec(''alter table Test add [' + @column + '] ' + @datatype + ' null'')
end

if(@oldCDataType != ''timestamp'')
begin

    set @columns += @oldC + '' , '' 
    set @columnVars += ''@'' + @oldC + '' , ''

    if(@oldCLen is null)
    begin
        if(@oldCDataType != ''uniqueidentifier'')
        begin
            set @printVars += '' print convert('' + @oldCDataType + '',@'' + @oldC + '')'' 
            set @columnsDecl += ''@'' + @oldC + '' '' + @oldCDataType + '', '' 
            exec(''alter table Test add ['' + @oldC + ''] '' + @oldCDataType + '' null'')
        end
        else
        begin
            set @printVars += '' print convert(varchar(50),@'' + @oldC + '')'' 
            set @columnsDecl += ''@'' + @oldC + '' '' + @oldCDataType + '', '' 
            exec(''alter table Test add ['' + @oldC + ''] '' + @oldCDataType + '' null'')
        end
    end
    else
    begin 
        if(@oldCLen < 0)
        begin
            set @oldCLen = 4000
        end
        set @printVars += '' print @'' + @oldC 
        set @columnsDecl += ''@'' + @oldC + '' '' + @oldCDataType + ''('' + convert(character,@oldCLen) + '') , '' 
        exec(''alter table Test add ['' + @oldC + ''] '' + @oldCDataType + ''('' + @oldCLen + '') null'')
    end
end

if exists (select column_name from INFORMATION_SCHEMA.COLUMNS where table_name = ''Test'' and column_name = ''dummy'')
begin
    alter table Test drop column dummy
end

FETCH NEXT FROM MY_CURSOR INTO  @oldC, @oldCDataType, @oldCLen, @oldCPos END CLOSE MY_CURSOR DEALLOCATE MY_CURSOR

set @columns = reverse(substring(reverse(@columns), charindex('','',reverse(@columns)) +1, len(@columns)))
set @columnVars = reverse(substring(reverse(@columnVars), charindex('','',reverse(@columnVars)) +1, len(@columnVars)))
set @columnsDecl = reverse(substring(reverse(@columnsDecl), charindex('','',reverse(@columnsDecl)) +1, len(@columnsDecl)))
set @columns = replace(replace(REPLACE(@columns, ''       '', ''''), char(9) + char(9),'' ''), char(9), '''')
set @columnVars = replace(replace(REPLACE(@columnVars, ''       '', ''''), char(9) + char(9),'' ''), char(9), '''')
set @columnsDecl = replace(replace(REPLACE(@columnsDecl, ''  '', ''''), char(9) + char(9),'' ''),char(9), '''')
set @printVars = REVERSE(substring(reverse(@printVars), charindex(''+'',reverse(@printVars))+1, len(@printVars))) 

create table query (id int identity(1,1), string varchar(max))

insert into query values  (''declare '' + @columnsDecl + ''
DECLARE MY_CURSOR CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR '')

insert into query values   (''select '' + @columns + '' from ' + @database + '._.' + @table + ''')

insert into query values  (''OPEN MY_CURSOR FETCH NEXT FROM MY_CURSOR INTO '' + @columnVars + '' WHILE @@FETCH_STATUS = 0 BEGIN '')

insert into query values   (@printVars )

insert into query values   ( '' insert into Test ('')
insert into query values   (@columns) 
insert into query values   ( '') values ( '' + @columnVars + '')'')

insert into query values  (''FETCH NEXT FROM MY_CURSOR INTO  '' + @columnVars + '' END CLOSE MY_CURSOR DEALLOCATE MY_CURSOR'')

declare @path varchar(100) = ''C:\query.sql''
declare @query varchar(500) = ''bcp "select string from query order by id" queryout '' + @path + '' -t, -c -S  '' + @@servername +  '' -T''

exec master..xp_cmdshell @query

set @query  = ''sqlcmd -S '' + @@servername + '' -i '' + @path

EXEC xp_cmdshell  @query

set @query = ''del ''  + @path

exec xp_cmdshell @query

drop table ' + @database + '._.' + @table + '

select * into ' + @database + '._.' + @table + ' from Test 

drop table query
drop table Test  ')

END

...