PostgreSQL 데이터베이스 테이블에서 열의 위치를 ​​어떻게 변경합니까?


답변:


106

" 바꿔 열 위치 PostgreSQL의 위키에"는 말합니다 :

PostgreSQL은 현재 테이블 의 attnum열을 기반으로 열 순서를 정의 pg_attribute합니다. 열 순서를 변경하는 유일한 방법은 테이블을 다시 만들거나 원하는 레이아웃에 도달 할 때까지 열을 추가하고 데이터를 회전하는 것입니다.

그것은 매우 약하지만 표준 SQL에서는 열 위치를 변경하는 솔루션이 없습니다. 열의 서수 위치 변경을 지원하는 데이터베이스 브랜드는 SQL 구문에 대한 확장을 정의하고 있습니다.

한 가지 다른 아이디어가 떠 오릅니다 VIEW. 기본 테이블에서 열의 물리적 위치를 변경하지 않고 원하는 방식으로 열 순서를 지정하는 a 를 정의 할 수 있습니다 .


3
@Dana : 그게 위키 기사에서 "테이블 다시 만들기"의 의미라고 생각합니다.
Bill Karwin

2
'데이터베이스 덤프':: 데이터를 손상시키는 좋은 방법. 따라서 "대량 데이터베이스 스크럽"효과.
Kent Fredric

31
@Kent : 의심 할 여지없이 postgres 개발자는 데이터 일관성을 보장하기 위해 먼 길을 가고 있으며 이는 확실히 pg_dump에 적용될 것입니다. 결국, 복원이 지루한 경우 db 백업을 수행하는 요점은 무엇입니까?
Dana the Sane

@Dana, 예,하지만 1) 덤프 할 큰 프로세스를 추가 한 다음 삭제하면 많은 시간이 소요되는로드가 발생합니다. 당신이있는 경우 심각 보통 37 개 컬럼의 경우 대규모 데이터베이스를, 당신은 디스크 IO의 질식 위험이 될 것입니다.
Kent Fredric

@DanatheSane 이것은 매우 오래된 주석이지만 Bill이 말한 것은 본질적으로 동일한 것입니다. 전체 데이터베이스 덤프를 수행하는 대신 테이블 (및 종속성)을 덤프하고 원본을 죽인 다음 다시 만듭니다. 전체 데이터베이스를 오프라인으로 전환하거나 영향을받지 않는 항목을 다시 만드는 데 시간을 할애 할 필요가 없습니다. 반면에 종속성이 많으면 전체 덤프를 수행하는 것이 훨씬 쉽다는 것을 알았습니다.
vol7ron

37

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;

4
와우, 대단합니다. 이것이 허용되는 대답이어야한다고 확신합니다!
Tommaso Thea Cioni

네, 정말 도움이 됐어요 정말 고마워요!
Acuna

다음과 같이 현재 테이블을 새 이전 테이블에 복사 할 수도 있습니다. CREATE TABLE oldtable AS SELECT * FROM tablename;
Ryan

29

이 게시물은 오래되었고 아마도 해결되었지만 동일한 문제가있었습니다. 새 열 순서를 지정하는 원래 테이블의보기를 만들어 해결했습니다.

여기에서 뷰를 사용하거나 뷰에서 새 테이블을 만들 수 있습니다.

    original_tab_vw 그대로보기 만들기
    a.col1, a.col3, a.col4, a.col2 선택
    from original_tab a
    a.col1이 NULL이 아닌 경우
    SELECT * INTO new_table FROM original_tab_vw

원래 테이블의 이름을 바꾸거나 삭제하고 새 테이블의 이름을 이전 테이블로 설정하십시오.


2
이것은 꽤 합리적인 해결책처럼 보입니다. 이 절차를 자동화하는 GUI 도구가 없다는 것은 너무 나쁩니다.
Quolonel 질문

4
좋은 솔루션이지만 데이터 유형 만 복사됩니다 (기본 키 없음 등)
Regisz

1
또는 재정렬 된 열이있는보기를 그대로 사용하십시오. 최소한의 성능 저하가 있어야합니다.
pscl

1
이것이 최상의 솔루션입니다.
Nikolay Shindarov

23

하나는 열 순서가 절대적으로 변경되어야하고 외래 키가 사용 중일 때 열을 재정렬하는 어색한 옵션이지만 먼저 데이터로 전체 데이터베이스를 덤프 한 다음 스키마 만 덤프하는 것입니다 ( pg_dump -s databasename > databasename_schema.sql). 다음으로 스키마 파일을 편집하여 원하는대로 열을 재정렬 한 다음 스키마에서 데이터베이스를 다시 만든 다음 마지막으로 새로 만든 데이터베이스로 데이터를 복원합니다.


1
왜 반대 투표입니까? 받아 들여진 대답에서 알 수 있듯이 PostgreSQL Wiki를 인용하면 다음과 같습니다.»열 순서를 변경하는 유일한 방법은 테이블을 다시 만들거나 원하는 레이아웃에 도달 할 때까지 열을 추가하고 데이터를 회전하는 것입니다.» 이 솔루션은 최적이 아니지만 (이러한 답변 중 어느 것도 작업을 수행하기위한 기본 제공 작업이없는 경우) 테이블의 열을 다시 정렬하는 방법을 제공합니다.
Ville

1
다시 말하지만,이 작업을 수행하는 좋은 방법은 없으며 위에서 설명한 내용 열이 절대적으로 재정렬되어야하는 경우 열을 재정렬하는 유효한 방법입니다. 내 답변에 반대하는 경우 허용되지 않는 해결책이라고 생각하는 이유에 대해 설명해주세요.
Ville

3
실제로 이것은 테이블이 다른 테이블의 외래 키일 때 매우 좋은 솔루션입니다. 다른 모든 솔루션은이 시나리오에서 작동하지 않습니다. 마지막으로, 사용 pg_dump의 --column-삽입 -s 여기서 databaseName> databasename_schema.sql
알레한드로 살라망카 Mazuelo


5

PGAdmin에서 테이블을 열고 하단의 SQL 창에서 SQL Create Table 문을 복사합니다. 그런 다음 검색어 도구를 열고 붙여 넣습니다. 테이블에 데이터가 있으면 테이블 이름을 'new_name'으로 변경하고 그렇지 않은 경우 테이블 삭제 행에서 주석 "-"을 삭제하십시오. 필요에 따라 열 순서를 편집하십시오. 이동 한 경우를 대비하여 마지막 열에서 누락 / 불필요한 쉼표에 유의하십시오. 새로운 SQL Create Table 명령을 실행합니다. 새로 고침 및 ... voilà.

디자인 단계의 빈 테이블의 경우이 방법은 매우 실용적입니다.

테이블에 데이터가있는 경우 데이터의 열 순서도 다시 정렬해야합니다. 이것은 쉽습니다. 다음을 사용 INSERT하여 이전 테이블을 새 버전으로 가져 오는 데 사용 합니다.

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

... 여기서 c2, c3, c1열이 c1, c2, c3새로운 위치에 이전 테이블의. 이 경우 편집 된 '이전'테이블에 '새'이름사용해야 합니다. 그렇지 않으면 데이터가 손실됩니다 . 열 이름이 많고 길거나 복잡한 경우 위와 동일한 방법을 사용하여 새 테이블 구조를 텍스트 편집기에 복사하고 INSERT문에 복사하기 전에 거기에 새 열 목록을 만듭니다 .

모든 것이 잘되었는지 확인한 후 DROP이전 테이블을 사용하여 'new'이름을 'old'로 변경하면 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 pseudotype이 필요하기 때문입니다. SELECT * 후 pg는 bigint 유형 insetad bigserial을 생성합니다.

4 단계 : 이제 뷰를 삭제하고 소스 테이블을 삭제하고 새 테이블의 이름을 이전 이름으로 바꿀 수 있습니다. 트릭은 성공적으로 끝났습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.