PostgreSQLデータベーステーブルの列の位置を変更するにはどうすればよいですか?


回答:


106

アルター列位置 PostgreSQLのWikiの中には、」言います:

PostgreSQLは現在attnumpg_attributeテーブルの列に基づいて列の順序を定義しています。列の順序を変更する唯一の方法は、テーブルを再作成するか、目的のレイアウトに到達するまで列を追加してデータをローテーションすることです。

それはかなり弱いですが、防御として、標準SQLでは、列を再配置するためのソリューションもありません。列の順序位置の変更をサポートするデータベースブランドは、SQL構文の拡張を定義しています。

もう1つのアイデアが思い浮かびVIEWます。基本テーブルでの列の物理的な位置を変更せずに、列の順序を好きなように指定するを定義できます。


3
@デーナ:Wiki記事の「テーブルを再作成する」とは、そういう意味だと思います。
ビルカーウィン

2
「データベースをダンプする」::データを損傷する素晴らしい方法。したがって、「大規模なデータベースを削除する」効果があります。
ケントフレドリック

31
@ケント:疑わしいことに、postgresの開発者はデータの一貫性を確保するために長い道のりを歩んでおり、それは確かにpg_dumpに当てはまります。結局のところ、復元が失敗した場合にdbバックアップを実行する意味は何ですか?
Dana the Sane

@Dana、そうですが、1)ダンプする大きなプロセスを追加し、それからドロップすると、時間のかかる負荷が大きくなります。非常大規模なデータベースを使用している場合(通常37列の場合)、ディスクIOのチョークによるリスクが発生します。
ケントフレドリック

@DanatheSaneこれらは非常に古いコメントですが、Billが言っていたことは基本的に同じことであり、完全なデータベースダンプを実行する代わりに、テーブル(および依存関係)をダンプし、元を削除してから再作成します。データベース全体をオフラインにしたり、影響を受けないものを作成し直したりする必要はありません。一方、多くの依存関係がある場合、フルダンプを実行すると(ご提案どおり)、はるかに簡単になります。
vol7ron、2012年

36

PostgreSQLでは、フィールドを追加するときに、テーブルの最後に追加されます。特定の位置に挿入する必要がある場合

alter table tablename rename to oldtable;
create table tablename (column defs go here);
insert into tablename (col1, col2, col3) select col1, col2, col3 from oldtable;

3
これはすごいです。これが受け入れられる答えになるはずです。
Tommaso Thea Cioni

ええ、それは本当に役に立ちます、本当にありがとう!
Acuna

次のように、現在のテーブルを新しいoldtableにコピーすることもできます。CREATE TABLE oldtable AS SELECT * FROM tablename;
ライアン

29

この投稿は古く、おそらく解決されましたが、同じ問題がありました。新しい列の順序を指定して、元のテーブルのビューを作成することで解決しました。

ここから、ビューを使用するか、ビューから新しいテーブルを作成できます。

    CREATE VIEW original_tab_vw AS
    SELECT a.col1、a.col3、a.col4、a.col2
    FROM original_tab a
    WHERE a.col1 IS NOT NULL-または何でも
    SELECT * INTO new_table FROM original_tab_vw

元のテーブルの名前を変更または削除し、新しいテーブルの名前を古いテーブルに設定します。


2
これはかなり合理的な解決策のようです。この手順を自動化するGUIツールがないのは残念です。
Quolonelの質問2014

4
適切なソリューションですが、データタイプのみがコピーされます(主キーなどはコピーされません)
Regisz '29

1
または、並べ替えられた列をそのまま使用してビューを使用します。パフォーマンスの低下は最小限でなければなりません。
pscl 2017

1
これが最良の解決策です。
ニコライ

23

1つは、列の順序を完全に変更する必要があり、外部キーが使用されている場合に列を再配置する不格好なオプションですが、最初にデータベース全体をデータでダンプし、次にスキーマのみをダンプすることです(pg_dump -s databasename > databasename_schema.sql)。次に、スキーマファイルを編集して、必要に応じて列を再配置し、スキーマからデータベースを再作成して、最後に、新しく作成したデータベースにデータを復元します。


1
なぜ反対票か。受け入れられた回答が指摘するように、PostgreSQL Wikiを引用します。»列の順序を変更する唯一の方法は、テーブルを再作成するか、目的のレイアウトに到達するまで列を追加してデータをローテーションすることです。» このソリューションは最適ではありませんが(これらの答えのいずれも、タスクを実行するための組み込み操作がない場合)、テーブルの列を再配置する方法を提供します。
ヴィル

1
もう一度言いますが、これを行うには良い方法はありません。上記概説したの、列を絶対に再配置する必要がある場合に列を再配置する有効な方法です。私の回答に反対票を投じる場合は、それが受け入れられない解決策であると思う理由についてコメントしてください。
Ville

3
実際、テーブルが別のテーブルの外部キーである場合、これは非常に優れたソリューションです。他のすべてのソリューションは、このシナリオでは機能しません。最後に、pg_dump --column-inserts -s databasename> databasename_schema.sqlを使用します
Alejandro Salamanca Mazuelo


5

PGAdminでテーブルを開き、下部のSQLペインでSQL Create Tableステートメントをコピーします。次に、クエリツールを開いて貼り付けます。テーブルにデータがある場合は、テーブル名を「new_name」に変更します。ない場合は、ドロップテーブル行のコメント「-」を削除します。必要に応じて列シーケンスを編集します。移動した場合に備えて、最後の列の欠落/余分なコンマに注意してください。新しいSQL Create Tableコマンドを実行します。リフレッシュして...ボイラ。

設計段階の空のテーブルの場合、この方法は非常に実用的です。

テーブルにデータがある場合、データの列シーケンスも再配置する必要があります。これは簡単です。次のコマンドを使用INSERTして、古いテーブルを新しいバージョンにインポートします。

INSERT INTO new ( c2, c3, c1 ) SELECT * from old;

...どこc2c3c1列がありc1c2c3彼らの新しい位置に古いテーブルの。この場合、編集した「古い」テーブルには「新しい」名前使用する必要あります。そうしないと、データが失われます。列名が多い、長い、または複雑な場合は、上記と同じ方法を使用して新しいテーブル構造をテキストエディターにコピーし、INSERTステートメントにコピーする前にそこで新しい列リストを作成します。

すべてが正常でDROPあることを確認した後、古いテーブルを使用して「新しい」名前を「古い」に変更するALTER TABLE new RENAME TO old;と、完了です。


1

私は多くのテーブルの並べ替えに取り組んでおり、同じクエリを何度も作成する必要がなかったので、それをすべて行うスクリプトを作成しました。基本的に、それは:

  1. からテーブル作成SQLを取得します pg_dump
  2. ダンプから使用可能なすべての列を取得します
  3. 列を希望の順序に配置します
  4. 元のpg_dumpクエリを変更して、データを含む並べ替えられたテーブルを作成します
  5. 古いテーブルを削除します
  6. 古いテーブルと一致するように新しいテーブルの名前を変更します

次の簡単なコマンドを実行して使用できます。

./reorder.py -n schema -d database table \
    first_col second_col ... penultimate_col ultimate_col --migrate

それはあなたがそれを検証してテストできるようにSQLを出力します、それが私がそれに基づいた大きな理由でしたpg_dump。あなたは見つけることができるここにgithubのレポを


0

私はDjangoを使用していますが、頭痛がしたくない場合は、各テーブルにid列が必要です。残念ながら、私は不注意で、自分のテーブルbp.geo_location_vagueにこのフィールドが含まれていませんでした。私は少しトリックを始めました。ステップ1:

CREATE VIEW bp.geo_location_vague_vw AS
    SELECT 
        a.id, -- I change order of id column here. 
        a.in_date,
        etc
    FROM bp.geo_location_vague a

ステップ2:(テーブルを作成しない-テーブルは自動的に作成されます!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

ステップ3:

CREATE SEQUENCE bp.tbl_tbl_id_seq;
ALTER TABLE bp.geo_location_vague_cp2 ALTER COLUMN id SET DEFAULT nextval('tbl_tbl_id_seq');
ALTER SEQUENCE bp.tbl_tbl_id_seq OWNED BY bp.geo_location_vague_cp2.id;
SELECT setval('tbl_tbl_id_seq', COALESCE(max(id), 0)) FROM bp.geo_location_vague_cp2;

テーブルにbigserial疑似タイプが必要だからです。SELECT *の後にpgを実行すると、bigint型のinsetad bigserialが作成されます。

ステップ4:これで、ビューをドロップし、ソーステーブルをドロップして、新しいテーブルの名前を古い名前に変更できます。トリックは無事終了しました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.