PostgreSQL veritabanı tablosundaki bir sütunun konumunu nasıl değiştirebilirim?


Yanıtlar:


107

" Alter sütun pozisyon PostgreSQL Wiki" diyor:

PostgreSQL şu anda sütun sırasını tablonun attnumsütununa göre tanımlamaktadır pg_attribute. Sütun sırasını değiştirmenin tek yolu, tabloyu yeniden oluşturmak veya istediğiniz düzene ulaşana kadar sütunlar ekleyip verileri döndürmektir.

Bu oldukça zayıf, ancak onların savunmasında, standart SQL'de bir sütunun yeniden konumlandırılması için de bir çözüm yoktur. Bir sütunun sıralı konumunu değiştirmeyi destekleyen veritabanı markaları, SQL sözdizimine bir uzantı tanımlıyor.

Aklıma başka bir fikir geliyor: VIEWTemel tablodaki sütunun fiziksel konumunu değiştirmeden, sütunların sırasını istediğiniz gibi belirten bir tanımlayabilirsiniz .


3
@Dana: Wiki makalesinde "tabloyu yeniden oluşturmak" ile kastedilen bu sanırım.
Bill Karwin

2
'veritabanını boşaltın' :: verilere zarar vermenin harika bir yolu. ve dolayısıyla "büyük veritabanını temizle" etkisi.
Kent Fredric

31
@Kent: Şüpheli, postgres geliştiricileri veri tutarlılığını sağlamak için uzun bir yol kat ediyor ve bu kesinlikle pg_dump için geçerli. Sonuçta, geri yükleme işliyse db yedeklemeleri yapmanın anlamı nedir?
Dana the Sane

@Dana, evet, ama 1) dökmek için büyük bir süreç ekliyorsun ve sonra bırakıyorsun ve sonra büyük bir zaman harcayan yükün var. Eğer bir varsa ciddi genellikle 37 sütunlu olduğu masif veritabanı, disk IO boğulma riskleri zorunda gidiyoruz.
Kent Fredric

@DanatheSane bunlar çok eski yorumlar, ancak Bill'in söylediği şey aslında aynı şey, tam bir veritabanı dökümü yapmak yerine, sadece tabloyu (ve bağımlılıkları) atarsınız, orijinali öldürür ve sonra yeniden yaratırsınız. Tüm veritabanını çevrimdışı duruma getirmeye veya etkilenmeyen bir şeyi yeniden oluşturmak için zaman harcamaya gerek yok. Öte yandan, çok fazla bağımlılık varsa, tam bir döküm yapmayı (önerdiğiniz gibi) çok daha kolay buldum.
vol7ron

38

PostgreSQL'de, bir alan eklenirken tablonun sonuna eklenir. Belirli bir konuma eklememiz gerekirse o zaman

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;

4
Vay canına, bu harika, eminim bu kabul edilen cevap olmalıdır!
Tommaso Thea Cioni

Evet, gerçekten yardımcı oldu, çok teşekkürler!
Acuna

Mevcut tabloyu yeni bir eski tabloya da kopyalayabilirsiniz: CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan

29

Bu gönderi eski ve muhtemelen çözüldü ama aynı sorunu yaşadım. Yeni sütun sırasını belirterek orijinal tablonun bir görünümünü oluşturarak bunu çözdüm.

Buradan görünümü kullanabilir veya görünümden yeni bir tablo oluşturabilirim.

    GÖRÜNÜM ORİJİNAL_tab_vw AS OLUŞTUR
    A.col1, a.col3, a.col4, a.col2 seçin
    FROM original_tab a
    A.col1 NULL OLMADIĞI YERDE - ya da her neyse
    Original_tab_vw’DEN new_table’ı SEÇİN

Orijinal tabloyu yeniden adlandırın veya bırakın ve yeni tablonun adını eski tabloya ayarlayın.


2
Bu oldukça makul bir çözüm gibi görünüyor. Bu prosedürü otomatikleştirmek için herhangi bir GUI aracının olmaması çok kötü.
Quolonel Soruları

4
iyi bir çözüm ancak yalnızca veri türleri kopyalanır (birincil anahtar yok, vb.)
Regisz

1
Alternatif olarak - görünümü yeniden sıralanan sütunlarla olduğu gibi kullanın. Minimum performans düşüşü olmalıdır.
pscl

1
Bu en iyi çözüm.
Nikolay Shindarov

23

Sütun sırasının kesinlikle değiştirilmesi gerektiğinde ve yabancı anahtarlar kullanımdayken sütunları yeniden düzenlemek için beceriksiz bir seçenek olsa da, önce tüm veritabanını verilerle dökmek, sonra yalnızca schema ( pg_dump -s databasename > databasename_schema.sql) ' yı dökmektir . Ardından, sütunları istediğiniz gibi yeniden düzenlemek için şema dosyasını düzenleyin, ardından veritabanını şemadan yeniden oluşturun ve son olarak verileri yeni oluşturulan veritabanına geri yükleyin.


1
Neden olumsuz oy? Kabul edilen yanıtın işaret ettiği gibi, PostgreSQL Wiki'den alıntı yaparak: »Sütun sırasını değiştirmenin tek yolu, tabloyu yeniden oluşturmak ya da istediğiniz düzene ulaşana kadar sütunlar eklemek ve verileri döndürmektir.» Bu çözüm optimal değildir (bu yanıtların hiçbiri, görevi yerine getirmek için yerleşik bir işlemin yokluğunda değildir), ancak bir tablodaki sütunları yeniden düzenlemek için bir yol sağlar.
Ville

1
Tekrar söylüyorum, bunu yapmanın iyi bir yolu yok ve yukarıda özetlediğim şey, sütunları kesinlikle yeniden düzenlenmeleri gerekiyorsa yeniden düzenlemenin geçerli bir yoludur. Cevabımı reddederseniz, lütfen bunun neden kabul edilemez bir çözüm olduğunu düşündüğünüzü yorumlayın.
Ville

3
Aslında, tablo başka bir tablodaki yabancı anahtar olduğunda bu çok iyi bir çözümdür. Diğer tüm çözümler bu escenario'da çalışmıyor. Son olarak, pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo


5

Tabloyu PGAdmin'de açın ve alttaki SQL bölmesinde SQL Create Table deyimini kopyalayın. Ardından Sorgu Aracı'nı açın ve yapıştırın. Tabloda veri varsa, tablo adını "yeni_ad" olarak değiştirin, yoksa Tabloyu Bırak satırındaki "-" açıklamasını silin. Sütun sırasını gerektiği gibi düzenleyin. Son sütundaki eksik / gereksiz virgülün yerini değiştirmiş olmanız ihtimaline dikkat edin. Yeni SQL Create Table komutunu yürütün. Yenileyin ve ... voilà.

Tasarım aşamasında boş masalar için bu yöntem oldukça pratiktir.

Tabloda veri olması durumunda, verilerin sütun sırasını da yeniden düzenlememiz gerekir. Bu kolaydır: INSERTeski tabloyu yeni sürümüne aktarmak için kullanın :

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

... nerede c2, c3, c1sütunlar vardır c1, c2, c3onların yeni pozisyonlarda eski tablonun. Lütfen bu durumda düzenlenen "eski" tablo için "yeni" bir ad kullanmanız gerektiğini , aksi takdirde verilerinizi kaybedeceğinizi unutmayın . Sütun adlarının çok, uzun ve / veya karmaşık olması durumunda, yeni tablo yapısını bir metin düzenleyicisine kopyalamak için yukarıdaki ile aynı yöntemi kullanın ve yeni sütun listesini,INSERT ifadeye .

Her şeyin yolunda olup olmadığını kontrol ettikten sonra DROP, eski tablo ve 'yeni' adını 'eski' olarak değiştirin ALTER TABLE new RENAME TO old;ve işiniz bitti.


1

Birçok tabloyu yeniden düzenlemek için çalışıyordum ve aynı sorguları defalarca yazmak zorunda kalmak istemiyordum, bu yüzden hepsini benim için yapmak için bir komut dosyası hazırladım. Esasen, o:

  1. Tablo oluşturma SQL'sini alır pg_dump
  2. Dökümden tüm kullanılabilir sütunları alır
  3. Sütunları istenilen sıraya koyar
  4. Verilerle pg_dumpyeniden sıralanmış bir tablo oluşturmak için orijinal sorguyu değiştirir
  5. Eski tabloyu düşürür
  6. Yeni tabloyu eski tabloyla eşleşecek şekilde yeniden adlandırır

Aşağıdaki basit komut çalıştırılarak kullanılabilir:

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

Doğrulayabilmeniz ve test edebilmeniz için sql'yi yazdırıyor, buna dayandırmamın büyük bir nedeni buydu pg_dump. Github deposunu burada bulabilirsiniz .


0

Django kullanıyorum ve baş ağrısı istemiyorsanız her tabloda id sütunu gerektirir. Maalesef dikkatsizdim ve bp.geo_location_vague tablomda bu alan yoktu. Küçük numara yaptım. Aşama 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

Adım 2: (tablo oluşturmadan - tablo otomatik olarak oluşturulacaktır!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Aşama 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;

Çünkü tabloda büyük seri pseudotipe ihtiyacım var. SELECT * 'den sonra pg'ye bigint tipi insetad bigserial oluşturulur.

4. adım: Şimdi görünümü bırakabilir, kaynak tabloyu bırakabilir ve yeni tabloyu eski adla yeniden adlandırabiliriz. Hile başarıyla sona erdi.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.