ฉันจะเปลี่ยนตำแหน่งของคอลัมน์ในตารางฐานข้อมูล PostgreSQL ได้อย่างไร


112

ฉันได้ลองทำสิ่งต่อไปนี้แล้ว แต่ไม่สำเร็จ:

ALTER TABLE person ALTER COLUMN dob POSITION 37;

6
คำถามนี้มีคำตอบก่อน
Tometzky

คำตอบ:


107

" แก้ไขตำแหน่งคอลัมน์ " ใน PostgreSQL Wiki พูดว่า:

ปัจจุบัน PostgreSQL กำหนดลำดับคอลัมน์ตามattnumคอลัมน์ของpg_attributeตาราง วิธีเดียวที่จะเปลี่ยนลำดับคอลัมน์คือการสร้างตารางใหม่หรือเพิ่มคอลัมน์และหมุนเวียนข้อมูลจนกว่าคุณจะได้รูปแบบที่ต้องการ

มันค่อนข้างอ่อนแอ แต่ในการป้องกันใน SQL มาตรฐานไม่มีวิธีแก้ปัญหาสำหรับการเปลี่ยนตำแหน่งคอลัมน์เช่นกัน แบรนด์ฐานข้อมูลที่รองรับการเปลี่ยนตำแหน่งลำดับของคอลัมน์กำลังกำหนดส่วนขยายของไวยากรณ์ SQL

อีกแนวคิดหนึ่งเกิดขึ้นกับฉัน: คุณสามารถกำหนด a VIEWที่ระบุลำดับของคอลัมน์ตามที่คุณต้องการโดยไม่ต้องเปลี่ยนตำแหน่งทางกายภาพของคอลัมน์ในตารางฐาน


3
@Dana: ฉันคิดว่านั่นหมายถึงการ "สร้างตารางใหม่" ในบทความวิกิ
Bill Karwin

2
'ถ่ายโอนฐานข้อมูล' :: วิธีที่ดีในการทำลายข้อมูล และด้วยเหตุนี้เอฟเฟกต์ "ขัดฐานข้อมูลขนาดใหญ่"
Kent Fredric

31
@ Kent: น่าสงสัยนักพัฒนา postgres ไปไกลเพื่อให้แน่ใจว่าข้อมูลมีความสอดคล้องกันและแน่นอนว่าจะนำไปใช้กับ pg_dump ท้ายที่สุดแล้วอะไรคือจุดของการสำรองข้อมูลฐานข้อมูลหากการกู้คืนถูก borked?
Dana the Sane

@Dana ใช่ แต่คุณกำลังเพิ่ม 1) กระบวนการใหญ่ในการถ่ายโอนข้อมูลจากนั้นคุณก็วางแล้วคุณจะต้องใช้เวลาโหลดนาน หากคุณมีอย่างจริงจังฐานข้อมูลขนาดใหญ่ซึ่งมักจะเป็นกรณีที่มี 37 คอลัมน์คุณกำลังจะมีความเสี่ยงกับ IO ดิสก์สำลัก
Kent Fredric

@DanatheSane สิ่งเหล่านี้เป็นความคิดเห็นที่เก่าแก่มาก แต่สิ่งที่ Bill พูดนั้นเป็นสิ่งเดียวกันแทนที่จะทำการถ่ายโอนข้อมูลฐานข้อมูลทั้งหมดคุณเพียงแค่ถ่ายโอนข้อมูลตาราง (และการอ้างอิง) ฆ่าต้นฉบับแล้วสร้างใหม่ ไม่จำเป็นต้องออฟไลน์ฐานข้อมูลทั้งหมดหรือใช้เวลาในการสร้างสิ่งที่ไม่ได้รับผลกระทบ ในทางกลับกันหากมีการอ้างอิงจำนวนมากฉันพบว่าการถ่ายโอนข้อมูลแบบเต็ม (ตามที่คุณแนะนำ) จะง่ายกว่ามาก
vol7ron

39

ใน 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;

5
ว้าวดีมากฉันแน่ใจว่านี่ควรเป็นคำตอบที่ยอมรับ!
Tommaso Thea Cioni

ใช่มันมีประโยชน์มากขอบคุณมาก!
Acuna

1
คุณยังสามารถคัดลอกตารางปัจจุบันไปยัง oldtable ใหม่ได้เช่นนี้: สร้างตาราง oldtable เป็นเลือก * จากชื่อตาราง;
Ryan

ทำงานได้อย่างสมบูรณ์ มันควรจะเป็นคำตอบที่ยอมรับได้จริงๆ!
ฮวน

29

โพสต์นี้เก่าและอาจแก้ไขได้ แต่ฉันมีปัญหาเดียวกัน ฉันแก้ไขได้โดยการสร้างมุมมองของตารางเดิมที่ระบุลำดับคอลัมน์ใหม่

จากตรงนี้ฉันสามารถใช้มุมมองหรือสร้างตารางใหม่จากมุมมอง

    สร้างมุมมอง original_tab_vw AS
    เลือก a.col1, a.col3, a.col4, a.col2
    จาก original_tab a
    โดยที่ a.col1 ไม่เป็นโมฆะ - หรืออะไรก็ตาม
    เลือก * INTO new_table จาก original_tab_vw

เปลี่ยนชื่อหรือวางตารางเดิมและตั้งชื่อตารางใหม่เป็นตารางเก่า


2
ดูเหมือนจะเป็นวิธีแก้ปัญหาที่สมเหตุสมผล มันแย่เกินไปที่ไม่มีเครื่องมือ GUI ที่จะทำให้ขั้นตอนนี้เป็นไปโดยอัตโนมัติ
คำถาม Quolonel

4
ทางออกที่ดี แต่คัดลอกเฉพาะประเภทข้อมูลเท่านั้น (ไม่มีคีย์หลัก ฯลฯ )
Regisz

1
อีกวิธีหนึ่ง - เพียงแค่ใช้มุมมองกับคอลัมน์ที่เรียงลำดับตามที่เป็นอยู่ ควรมีการลดประสิทธิภาพการทำงานน้อยที่สุด
pscl

1
นี่คือทางออกที่ดีที่สุด
Nikolay Shindarov

23

หนึ่งแม้ว่าตัวเลือกที่งุ่มง่ามในการจัดเรียงคอลัมน์ใหม่เมื่อต้องเปลี่ยนลำดับคอลัมน์อย่างแน่นอนและมีการใช้คีย์ต่างประเทศคือการถ่ายโอนข้อมูลฐานข้อมูลทั้งหมดด้วยข้อมูลก่อนจากนั้นจึงถ่ายโอนข้อมูลเพียง schema ( pg_dump -s databasename > databasename_schema.sql) จากนั้นแก้ไขไฟล์สคีมาเพื่อจัดเรียงคอลัมน์ใหม่ตามที่คุณต้องการจากนั้นสร้างฐานข้อมูลใหม่จากสคีมาและสุดท้ายคืนค่าข้อมูลลงในฐานข้อมูลที่สร้างขึ้นใหม่


1
ทำไมต้องโหวตลด? ดังที่คำตอบที่ยอมรับได้ชี้ให้เห็นการอ้างถึง PostgreSQL Wiki: »วิธีเดียวที่จะเปลี่ยนลำดับคอลัมน์คือการสร้างตารางใหม่หรือโดยการเพิ่มคอลัมน์และหมุนเวียนข้อมูลจนกว่าคุณจะได้รูปแบบที่ต้องการ» โซลูชันนี้ไม่เหมาะสมที่สุด (ไม่มีคำตอบเหล่านี้ในกรณีที่ไม่มีการดำเนินการในตัวเพื่อให้งานสำเร็จ) แต่จะมีวิธีจัดเรียงคอลัมน์ในตารางใหม่
Ville

1
ฉันพูดอีกครั้งไม่มีวิธีที่ดีในการทำเช่นนี้และสิ่งที่ฉันร่างไว้ข้างต้นเป็นวิธีที่ถูกต้องในการจัดเรียงคอลัมน์ใหม่หากต้องจัดเรียงใหม่อย่างแน่นอน หากคุณไม่ลงคะแนนคำตอบของฉันโปรดแสดงความคิดเห็นว่าเหตุใดคุณจึงคิดว่าเป็นวิธีแก้ปัญหาที่ไม่สามารถยอมรับได้
Ville

3
อันที่จริงนี่เป็นวิธีแก้ปัญหาที่ดีมากเมื่อตารางเป็นคีย์ต่างประเทศในตารางอื่น โซลูชันอื่นทั้งหมดใช้ไม่ได้ในเอสเคนาริโอนี้ สุดท้ายใช้ pg_dump --column-inserts -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo

9

ผมไม่คิดว่าคุณสามารถในปัจจุบันดูบทความนี้ในวิกิพีเดีย PostgreSQL

วิธีแก้ปัญหาสามประการจากบทความนี้คือ:

  1. สร้างตารางใหม่
  2. เพิ่มคอลัมน์และย้ายข้อมูล
  3. ซ่อนความแตกต่างด้วยมุมมอง

5

เปิดตารางใน PGAdmin และในบานหน้าต่าง SQL ที่ด้านล่างคัดลอกคำสั่ง SQL Create Table จากนั้นเปิดเครื่องมือสืบค้นข้อมูลและวาง หากตารางมีข้อมูลให้เปลี่ยนชื่อตารางเป็น "new_name" หากไม่มีให้ลบความคิดเห็น "-" ในบรรทัดวางตาราง แก้ไขลำดับคอลัมน์ตามต้องการ คำนึงถึงเครื่องหมายจุลภาคที่ขาดหายไป / ไม่จำเป็นในคอลัมน์สุดท้ายในกรณีที่คุณย้ายไป ดำเนินการคำสั่งสร้างตาราง SQL ใหม่ รีเฟรชและ ... voila

สำหรับตารางเปล่าในขั้นตอนการออกแบบวิธีนี้ใช้ได้จริง

ในกรณีที่ตารางมีข้อมูลเราจำเป็นต้องจัดเรียงลำดับคอลัมน์ของข้อมูลใหม่ด้วย ง่ายมาก: ใช้INSERTเพื่อนำเข้าตารางเก่าไปยังเวอร์ชันใหม่ด้วย:

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

... ที่c2, c3, c1มีคอลัมน์c1, c2, c3ของตารางเก่าในตำแหน่งใหม่ของพวกเขา โปรดทราบว่าในกรณีนี้คุณต้องใช้ชื่อ 'ใหม่'สำหรับตาราง 'เก่า' ที่แก้ไขไม่เช่นนั้นข้อมูลของคุณจะสูญหาย ในกรณีที่ชื่อคอลัมน์มีจำนวนมากยาวและ / หรือซับซ้อนให้ใช้วิธีการเดียวกับด้านบนเพื่อคัดลอกโครงสร้างตารางใหม่ลงในโปรแกรมแก้ไขข้อความและสร้างรายการคอลัมน์ใหม่ที่นั่นก่อนที่จะคัดลอกลงใน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เพื่อให้คุณสามารถตรวจสอบและการทดสอบมันนั่นคือเหตุผลที่ผมใหญ่ขึ้นอยู่บน คุณสามารถค้นหาrepo GitHub ที่นี่


0

ฉันใช้ Django และต้องใช้คอลัมน์รหัสในแต่ละตารางหากคุณไม่ต้องการปวดหัว น่าเสียดายที่ฉันประมาทและตาราง 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;

เพราะฉันต้องมีนามแฝงขนาดใหญ่ในตาราง หลังจาก SELECT * ลงใน pg จะสร้างประเภท bigint insetad bigserial

ขั้นตอนที่ 4: ตอนนี้เราสามารถวางมุมมองวางตารางแหล่งที่มาและเปลี่ยนชื่อตารางใหม่ในชื่อเก่า เคล็ดลับจบลงด้วยความเรียบร้อย


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.