web-dev-qa-db-ja.com

特定の列の後にSQLで列を追加する方法は?

私はテーブルを持っています:

MyTable
    ID
    FieldA
    FieldB

テーブルを変更し、列を追加して、次のようにします。

MyTable
    ID
    NewField
    FieldA
    FieldB

MySQLでは次のようにします。

ALTER TABLE MyTable ADD COLUMN NewField int NULL AFTER ID;

1行、ニース、シンプル、素晴らしい作品。マイクロソフトの世界でこれを行うにはどうすればよいですか?

35
Justin808

残念ながらできません。

その順序で本当に必要な場合は、その順序で列を持つ新しいテーブルを作成し、データをコピーする必要があります。または列などの名前を変更します。簡単な方法はありません。

32
Mike M.

溶液:

これは、カスケードイベントをトリガーする変更中のテーブルに依存関係がないテーブルで機能します。 最初に、壊滅的な影響なしに再構築するテーブルを削除できることを確認してください。すべての依存関係をメモし、テーブルに関連付けられている列制約(トリガー、インデックスなど)。完了したら、元に戻す必要があります。

ステップ1:一時テーブルを作成して、再構築するテーブルのすべてのレコードを保持します。 new columnを含めることを忘れないでください。

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
)

STEP 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_myTablemyTable_Copyを削除する代わりに名前を変更することを選択した場合は、テーブルを削除します。

6
Milan

Management StudioのGUIを使用して列を作成する場合、これを実行できるはずです。 Management Studioは実際にテーブルを完全に再作成しているため、これが発生しているようです。

他の人が述べたように、テーブル内の列の順序は重要ではなく、もしそうなら、コードに何か問題があります。

3
Abe Miessler

/ *テーブルの列順序を変更するスクリプト
元のテーブルを置き換える新しいテーブルが作成されることに注意してください
ただし、トリガーやその他のテーブルプロパティはコピーしません-データのみ
* /

必要な順序で列を持つ新しいテーブルを生成する

Select Column2, Column1, Column3 Into NewTable from OldTable

元のテーブルを削除する

Drop Table OldTable;

新しいテーブルの名前を変更する

EXEC sp_rename 'NewTable', 'OldTable';

2
Glyn

SQL Enterprise Management Studioでテーブルを開き、必要な場所に列を追加し、変更を保存する代わりに、変更スクリプトを生成します。 SQLでどのように実行されるかを確認できます。

要するに、他の人が言ったことは正しい。 SQL Management Studioは、すべてのデータを一時テーブルにプルし、テーブルを削除し、列を正しい順序で再作成して、一時テーブルデータをそこに戻します。特定の位置に列を追加するための単純な構文はありません。

1
user2124444

テーブルを再構築する必要があります。幸いなことに、列の順序はまったく関係ありません!

列を魔法のように並べ替えるのを見てください:

SELECT ID, Newfield, FieldA, FieldB FROM MyTable

また、これは以前に何十億回も質問されています。

1
JNK

質問が古い場合でも、Management Studioに関するより正確な回答が必要です。

列は手動で作成することも、Management Studioを使用して作成することもできます。ただし、Management Studioではテーブルを再作成する必要があり、既にデータが多すぎる場合はタイムアウトになります。テーブルが軽い場合を除き、避けてください。

列の順序を変更するには、Management Studioで列を移動するだけです。テーブル定義の列の順序を変更する可能性が高いため、Management Studioがテーブルを再作成する必要はありません(例外が存在する可能性が高い)。

私は、テーブル内のデータが原因でGUIで列を追加できなかったテーブルを使用して、何度もこの方法を実行しました。次に、Management StudioのGUIを使用して列を移動し、単純に保存しました。

確実なタイムアウトから数秒の待機になります。

1
Rv3

Microsoft SQL Server Management Studio(MSSQLの管理ツール)で、テーブルの「デザイン」に入り、列を新しい位置にドラッグします。コマンドラインではなく、あなたはそれを行うことができます。

1
paparazzo

これは絶対に可能です。あなたが何を扱っているかを知らない限り、あなたはそれをすべきではありませんが。それを理解するために約2日かかりました。入力するストアドプロシージャは次のとおりです。---データベース名(読みやすいようにスキーマ名は "_")---テーブル名--- column --- columnデータ型(追加された列は常にnullです。挿入可能)---新しい列の位置。

私はSAMツールキットのテーブルを使用しているため(一部のカラムには80カラム以上あります)、典型的な変数にはクエリを含めることができません。そのため、外部ファイルが必要になります。そのファイルを保存する場所と、NTFSおよびネットワークレベルでアクセスできるユーザーに注意してください。

乾杯!

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  ')

終わり

0