Bagaimana cara mengubah posisi kolom di tabel database PostgreSQL?

Jawaban:

107

" Ubah posisi kolom " di Wiki PostgreSQL mengatakan:

PostgreSQL saat ini mendefinisikan urutan kolom berdasarkan attnumkolom pg_attributetabel. Satu-satunya cara untuk mengubah urutan kolom adalah dengan membuat ulang tabel, atau dengan menambahkan kolom dan memutar data hingga Anda mencapai tata letak yang diinginkan.

Itu cukup lemah, tetapi dalam pertahanan mereka, dalam SQL standar, tidak ada solusi untuk memposisikan ulang kolom juga. Merek database yang mendukung perubahan posisi ordinal kolom mendefinisikan ekstensi ke sintaks SQL.

Satu gagasan lain muncul pada saya: Anda dapat menentukan a VIEWyang menentukan urutan kolom sesuka Anda, tanpa mengubah posisi fisik kolom di tabel dasar.

Bill Karwin
sumber
3
@Dana: Saya pikir itulah yang dimaksud dengan "membuat ulang tabel" di artikel wiki.
Bill Karwin
2
'dump the database' :: cara yang bagus untuk merusak data. dan karenanya "menghapus database besar-besaran".
Kent Fredric
31
@Kent: Diragukan, pengembang postgres berusaha keras untuk memastikan konsistensi data dan itu pasti akan berlaku untuk pg_dump. Lagi pula, apa gunanya melakukan backup db jika pemulihan terhenti?
Dana the Sane
@Dana, ya, tetapi Anda menambahkan 1) proses besar untuk dibuang, lalu Anda jatuhkan, dan kemudian Anda akan menghabiskan banyak waktu. Jika Anda memiliki database yang sangat besar, yang biasanya terjadi dengan 37 kolom, Anda akan memiliki risiko disk IO tersedak.
Kent Fredric
@DanatheSane ini adalah komentar yang sangat lama , tetapi apa yang dikatakan Bill pada dasarnya adalah hal yang sama, alih-alih melakukan dump database penuh, Anda hanya membuang tabel (dan dependensi), mematikan yang asli, lalu membuat ulang. Tidak perlu membuat seluruh database offline, atau menghabiskan waktu membuat ulang sesuatu yang tidak terpengaruh. Di sisi lain, jika ada banyak dependensi, menurut saya melakukan dump lengkap (seperti yang Anda sarankan) jauh lebih mudah.
vol7ron
37

Di PostgreSQL, sambil menambahkan bidang, itu akan ditambahkan di akhir tabel. Jika kita perlu memasukkan ke posisi tertentu maka

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;
Allwin
sumber
4
Wow ini bagus, saya yakin ini harus menjadi jawaban yang diterima!
Tommaso Thea Cioni
Ya, itu sangat membantu, terima kasih banyak!
Acuna
Anda juga dapat menyalin tabel saat ini ke tabel lama baru seperti ini: CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan
29

Posting ini sudah lama dan mungkin sudah terpecahkan tetapi saya memiliki masalah yang sama. Saya menyelesaikannya dengan membuat tampilan tabel asli yang menentukan urutan kolom baru.

Dari sini saya bisa menggunakan view atau membuat tabel baru dari view.

    BUAT TAMPILAN original_tab_vw AS
    PILIH a.col1, a.col3, a.col4, a.col2
    DARI original_tab a
    DI MANA a.col1 TIDAK NIHIL —atau apalah
    PILIH * KE new_table DARI original_tab_vw

Ubah nama atau jatuhkan tabel asli dan atur nama tabel baru ke tabel lama.

Ken
sumber
2
Ini sepertinya solusi yang cukup masuk akal. Sayang sekali tidak ada alat GUI untuk mengotomatiskan prosedur ini.
Pertanyaan Quolonel
4
solusi yang baik tetapi hanya tipe datanya yang disalin (tanpa kunci primer, dll.)
Regisz
1
Atau - cukup gunakan tampilan dengan kolom yang disusun ulang sebagaimana adanya. Harus ada penurunan kinerja minimal.
pscl
1
Ini solusi terbaik.
Nikolay Shindarov
23

Satu, meskipun merupakan opsi yang canggung untuk mengatur ulang kolom ketika urutan kolom harus benar-benar diubah, dan kunci asing digunakan, pertama-tama membuang seluruh database dengan data, lalu membuang hanya schema ( pg_dump -s databasename > databasename_schema.sql). Selanjutnya edit file skema untuk mengatur ulang kolom seperti yang Anda inginkan, lalu buat ulang database dari skema, dan terakhir pulihkan data ke database yang baru dibuat.

Ville
sumber
1
Mengapa suara negatif? Seperti yang ditunjukkan jawaban yang diterima, mengutip Wiki PostgreSQL: »Satu-satunya cara untuk mengubah urutan kolom adalah dengan membuat ulang tabel, atau dengan menambahkan kolom dan memutar data hingga Anda mencapai tata letak yang diinginkan.» Solusi ini tidak optimal (tidak ada dari jawaban ini yang tidak memiliki operasi bawaan untuk menyelesaikan tugas), tetapi menyediakan cara untuk mengatur ulang kolom dalam tabel.
Ville
1
Saya katakan lagi, tidak ada cara yang baik untuk melakukan ini, dan apa yang saya uraikan di atas adalah cara yang valid untuk mengatur ulang kolom jika benar-benar harus diatur ulang. Jika Anda tidak menyukai jawaban saya, beri komentar mengapa menurut Anda itu solusi yang tidak dapat diterima.
Ville
3
Faktanya, ini adalah solusi yang sangat baik ketika tabel adalah kunci asing di tabel lain. Semua solusi lain tidak berfungsi dalam skenario ini. Terakhir, gunakan pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo
9

Saya rasa Anda tidak bisa saat ini: lihat artikel ini di wiki Postgresql .

Tiga solusi dari artikel ini adalah:

  1. Buat ulang tabel
  2. Tambahkan kolom dan pindahkan data
  3. Sembunyikan perbedaan dengan tampilan.
Mike Woodhouse
sumber
5

Buka tabel di PGAdmin dan di panel SQL di bagian bawah salin pernyataan SQL Create Table. Kemudian buka Alat Kueri dan tempel. Jika tabel memiliki data, ubah nama tabel menjadi 'new_name', jika tidak, hapus komentar "-" di baris Drop Table. Edit urutan kolom sesuai kebutuhan. Perhatikan koma yang hilang / berlebihan di kolom terakhir jika Anda telah memindahkannya. Jalankan perintah SQL Create Table baru. Segarkan dan ... voila.

Untuk tabel kosong pada tahap desain cara ini cukup praktis.

Jika tabel memiliki data, kita perlu mengatur ulang urutan kolom datanya juga. Ini mudah: gunakan INSERTuntuk mengimpor tabel lama ke versi barunya dengan:

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

... di mana c2, c3, c1adalah kolom c1, c2, c3dari meja tua di posisi baru mereka. Harap dicatat bahwa dalam hal ini Anda harus menggunakan nama 'baru' untuk tabel 'lama' yang telah diedit, atau Anda akan kehilangan data Anda . Jika nama kolomnya banyak, panjang dan / atau kompleks, gunakan metode yang sama seperti di atas untuk menyalin struktur tabel baru ke editor teks, dan buat daftar kolom baru di sana sebelum menyalinnya ke dalam INSERTpernyataan.

Setelah memeriksa bahwa semuanya baik-baik saja, DROPtabel lama dan ubah nama 'baru' menjadi 'lama' menggunakan ALTER TABLE new RENAME TO old;dan Anda selesai.

marcopolo.dll
sumber
1

Saya sedang mengerjakan pemesanan ulang banyak tabel dan tidak ingin menulis kueri yang sama berulang kali, jadi saya membuat skrip untuk melakukan semuanya untuk saya. Intinya, ini:

  1. Mendapatkan SQL dari pembuatan tabel pg_dump
  2. Mendapatkan semua kolom yang tersedia dari dump
  3. Menempatkan kolom dalam urutan yang diinginkan
  4. Mengubah pg_dumpkueri asli untuk membuat tabel yang diurutkan ulang dengan data
  5. Menjatuhkan meja lama
  6. Ubah nama tabel baru agar sesuai dengan tabel lama

Ini dapat digunakan dengan menjalankan perintah sederhana berikut:

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

Ini mencetak sql sehingga Anda dapat memverifikasi dan mengujinya, itulah alasan utama saya mendasarkannya pg_dump. Anda dapat menemukan repo github di sini .

GammaGames
sumber
0

Saya menggunakan Django dan membutuhkan kolom id di setiap tabel jika anda tidak ingin pusing. Sayangnya, saya ceroboh dan tabel saya bp.geo_location_vague tidak berisi bidang ini. Saya memulai trik kecil. Langkah 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

Langkah 2: (tanpa membuat tabel - tabel akan dibuat secara otomatis!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Langkah 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;

Karena saya perlu memiliki pseudotype seri besar di tabel. Setelah SELECT * menjadi pg akan membuat tipe bigint insetad bigserial.

langkah 4: Sekarang kita dapat melepaskan tampilan, melepaskan tabel sumber dan mengganti nama tabel baru dengan nama lama. Triknya berhasil diakhiri.

Orlov Const
sumber