Làm cách nào để thay đổi vị trí của một cột trong bảng cơ sở dữ liệu PostgreSQL?


Câu trả lời:


106

" Vị trí cột thay thế " trong Wiki PostgreSQL cho biết:

PostgreSQL hiện xác định thứ tự cột dựa trên attnumcột của pg_attributebảng. Cách duy nhất để thay đổi thứ tự cột là tạo lại bảng hoặc thêm cột và xoay dữ liệu cho đến khi bạn đạt được bố cục mong muốn.

Điều đó khá yếu, nhưng để bảo vệ họ, trong SQL tiêu chuẩn, không có giải pháp nào để định vị lại một cột. Các thương hiệu cơ sở dữ liệu hỗ trợ thay đổi vị trí thứ tự của cột đang xác định một phần mở rộng cho cú pháp SQL.

Một ý tưởng khác xảy ra với tôi: bạn có thể xác định một VIEWchỉ định thứ tự của các cột theo cách bạn muốn, mà không thay đổi vị trí thực của cột trong bảng cơ sở.


3
@Dana: Tôi nghĩ đó là ý nghĩa của việc "tạo lại bảng" trong bài báo wiki.
Bill Karwin

2
'dump cơ sở dữ liệu' :: cách tuyệt vời để làm hỏng dữ liệu. và do đó có tác dụng "làm sạch cơ sở dữ liệu khổng lồ".
Kent Fredric

31
@Kent: Thật đáng nghi ngờ, các nhà phát triển postgres đã đi một chặng đường dài để đảm bảo tính nhất quán của dữ liệu và điều đó chắc chắn sẽ áp dụng cho pg_dump. Rốt cuộc, mục đích của việc sao lưu db nếu khôi phục bị khóa là gì?
Dana the Sane

@Dana, vâng, nhưng bạn đang thêm 1) một quá trình lớn để kết xuất, và sau đó bạn giảm xuống, và sau đó bạn có một tải trọng thời gian lớn. Nếu bạn có một cơ sở dữ liệu khổng lồ nghiêm trọng , thường là trường hợp có 37 cột, bạn sẽ gặp rủi ro với việc làm nghẹt đĩa IO.
Kent Fredric

@DanatheSane đây là những nhận xét quá , nhưng những gì Bill đã nói về cơ bản giống nhau, thay vì thực hiện kết xuất toàn bộ cơ sở dữ liệu, bạn chỉ cần kết xuất bảng (và các phần phụ thuộc), hủy bản gốc, sau đó tạo lại. Không cần phải sử dụng toàn bộ cơ sở dữ liệu ngoại tuyến hoặc dành thời gian tạo lại thứ gì đó không bị ảnh hưởng. Mặt khác, nếu có nhiều phụ thuộc, tôi thấy thực hiện kết xuất đầy đủ (như bạn đã đề xuất) dễ dàng hơn nhiều.
vol7ron

36

Trong PostgreSQL, khi thêm một trường, nó sẽ được thêm vào cuối bảng. Nếu chúng ta cần chèn vào vị trí cụ thể thì

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
Chà, điều này thật tuyệt, tôi chắc rằng đây phải là câu trả lời được chấp nhận!
Tommaso Thea Cioni

Vâng, nó thực sự hữu ích, cảm ơn rất nhiều!
Acuna

Bạn cũng có thể sao chép bảng hiện tại sang một bảng cũ mới như sau: CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan

29

Bài đăng này đã cũ và có thể đã được giải quyết nhưng tôi đã gặp vấn đề tương tự. Tôi đã giải quyết nó bằng cách tạo chế độ xem bảng gốc chỉ định thứ tự cột mới.

Từ đây, tôi có thể sử dụng chế độ xem hoặc tạo một bảng mới từ chế độ xem.

    TẠO XEM original_tab_vw NHƯ
    CHỌN a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    Ở đâu a.col1 KHÔNG ĐỦ - hoặc bất cứ điều gì
    CHỌN * VÀO new_table TỪ original_tab_vw

Đổi tên hoặc bỏ bảng ban đầu và đặt tên của bảng mới thành bảng cũ.


2
Đây có vẻ là một giải pháp khá hợp lý. Thật tệ là không có bất kỳ công cụ GUI nào để tự động hóa quy trình này.
Câu hỏi Quolonel

4
giải pháp tốt nhưng chỉ có các kiểu dữ liệu được sao chép (không khóa chính, vv)
Regisz

1
Ngoài ra - chỉ cần sử dụng dạng xem với các cột được sắp xếp lại nguyên trạng. Nên có sự suy giảm hiệu suất tối thiểu.
pscl 14/02/17

1
Đây là giải pháp tốt nhất.
Nikolay Shindarov

23

Một, mặc dù một tùy chọn vụng về để sắp xếp lại các cột khi thứ tự cột hoàn toàn phải thay đổi và các khóa ngoại đang được sử dụng, trước tiên là kết xuất toàn bộ cơ sở dữ liệu với dữ liệu, sau đó chỉ kết xuất lược đồ ( pg_dump -s databasename > databasename_schema.sql). Tiếp theo chỉnh sửa tệp lược đồ để sắp xếp lại các cột theo ý muốn, sau đó tạo lại cơ sở dữ liệu từ lược đồ, cuối cùng là khôi phục dữ liệu vào cơ sở dữ liệu mới tạo.


1
Tại sao lại ủng hộ? Như câu trả lời được chấp nhận đã chỉ ra, trích dẫn PostgreSQL Wiki: »Cách duy nhất để thay đổi thứ tự cột là tạo lại bảng hoặc bằng cách thêm cột và xoay dữ liệu cho đến khi bạn đạt được bố cục mong muốn.» Giải pháp này không phải là tối ưu (không có câu trả lời nào trong số này là không có hoạt động tích hợp để hoàn thành nhiệm vụ), nhưng nó cung cấp một cách để sắp xếp lại các cột trong bảng.
Ville

1
Tôi nói lại, không có cách nào tốt để làm điều này và những gì tôi phác thảo ở trên một cách hợp lệ để sắp xếp lại các cột nếu chúng hoàn toàn phải được sắp xếp lại. Nếu bạn không tán thành câu trả lời của tôi, hãy bình luận tại sao bạn cảm thấy đó là một giải pháp không thể chấp nhận được.
Ville

3
Trong thực tế, đây là một giải pháp rất tốt khi bảng là khóa ngoại trong các bảng khác. Tất cả các giải pháp khác không hoạt động trong escenario này. Cuối cùng, sử dụng pg_dump --column-chèn -s databasename> databasename_schema.sql
Alejandro Salamanca Mazuelo


5

Mở bảng trong PGAdmin và trong ngăn SQL ở dưới cùng, sao chép câu lệnh SQL Create Table. Sau đó, mở Công cụ truy vấn và dán. Nếu bảng có dữ liệu, hãy đổi tên bảng thành 'new_name', nếu không, hãy xóa chú thích "-" trong dòng Drop Table. Chỉnh sửa trình tự cột theo yêu cầu. Lưu ý dấu phẩy bị thiếu / thừa ở cột cuối cùng trong trường hợp bạn đã di chuyển nó. Thực thi lệnh SQL Create Table mới. Làm mới và ... voilà.

Đối với các bàn trống trong giai đoạn thiết kế, phương pháp này khá thực tế.

Trong trường hợp bảng có dữ liệu, chúng ta cũng cần sắp xếp lại trình tự cột của dữ liệu. Điều này rất dễ dàng: sử dụng INSERTđể nhập bảng cũ vào phiên bản mới của nó với:

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

... nơi c2, c3, c1là các cột c1, c2, c3của bảng cũ ở các vị trí mới của họ. Xin lưu ý rằng trong trường hợp này, bạn phải sử dụng tên 'mới' cho bảng 'cũ' đã chỉnh sửa, nếu không bạn sẽ mất dữ liệu của mình . Trong trường hợp tên cột nhiều, dài và / hoặc phức tạp, hãy sử dụng phương pháp tương tự như trên để sao chép cấu trúc bảng mới vào trình soạn thảo văn bản và tạo danh sách cột mới ở đó trước khi sao chép vào INSERTcâu lệnh.

Sau khi kiểm tra tất cả đều ổn, bạn hãy DROPsử dụng bảng cũ và thay đổi tên 'mới' thành 'cũ' ALTER TABLE new RENAME TO old;là xong.


1

Tôi đang làm việc để sắp xếp lại rất nhiều bảng và không muốn phải viết đi viết lại các truy vấn giống nhau nên tôi đã tạo một kịch bản để làm tất cả cho tôi. Về cơ bản, nó:

  1. Lấy SQL tạo bảng từ pg_dump
  2. Lấy tất cả các cột có sẵn từ bãi chứa
  3. Đặt các cột theo thứ tự mong muốn
  4. Sửa đổi pg_dumptruy vấn ban đầu để tạo bảng được sắp xếp lại với dữ liệu
  5. Bỏ bàn cũ
  6. Đổi tên bảng mới để khớp với bảng cũ

Nó có thể được sử dụng bằng cách chạy lệnh đơn giản sau:

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

Nó in ra sql để bạn có thể xác minh và kiểm tra nó, đó là lý do lớn mà tôi dựa vào nó pg_dump. Bạn có thể tìm thấy repo github tại đây .


0

Tôi sử dụng Django và nó yêu cầu cột id trong mỗi bảng nếu bạn không muốn đau đầu. Thật không may, tôi đã bất cẩn và bảng bp.geo_location_vague của tôi không chứa trường này. Tôi đã viết tắt một mẹo nhỏ. Bước 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

Bước 2: (không tạo bảng - bảng sẽ tạo tự động!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Bước 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;

Bởi vì tôi cần phải có bút danh bigserial trong bảng. Sau khi SELECT * vào pg sẽ tạo ra kiểu bigint insetad bigserial.

Bước 4: Bây giờ chúng ta có thể bỏ chế độ xem, bỏ bảng nguồn và đổi tên bảng mới theo tên cũ. Thủ thuật đã được kết thúc thành công.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.