[database] 기존 ENUM 유형에 새 값 추가

enum유형 을 사용하는 테이블 열이 있습니다. enum가능한 추가 값을 갖도록 해당 유형 을 업데이트하고 싶습니다 . 기존 값을 삭제하고 싶지 않고 새 값을 추가하십시오. 가장 간단한 방법은 무엇입니까?



답변

참고 PostgreSQL 9.1 이상을 사용 중이고 트랜잭션 외부에서 변경을 수행해도 괜찮은 경우 더 간단한 접근 방법 은 이 답변 을 참조하십시오 .


며칠 전에 같은 문제가 있었고이 게시물을 찾았습니다. 그래서 내 대답은 해결책을 찾는 사람에게 도움이 될 수 있습니다. 🙂

변경할 열거 형을 사용하는 하나 또는 두 개의 열만있는 경우이를 시도 할 수 있습니다. 또한 새 유형의 값 순서를 변경할 수 있습니다.

-- 1. rename the enum type you want to change
alter type some_enum_type rename to _some_enum_type;
-- 2. create new type
create type some_enum_type as enum ('old', 'values', 'and', 'new', 'ones');
-- 3. rename column(s) which uses our enum type
alter table some_table rename column some_column to _some_column;
-- 4. add new column of new type
alter table some_table add some_column some_enum_type not null default 'new';
-- 5. copy values to the new column
update some_table set some_column = _some_column::text::some_enum_type;
-- 6. remove old column and type
alter table some_table drop column _some_column;
drop type _some_enum_type;

하나 이상의 열이 있으면 3-6을 반복해야합니다.


답변

PostgreSQL 9.1 은 다음과 같은 ALTER 열거 형 기능을 제공 합니다.

ALTER TYPE enum_type ADD VALUE 'new_value'; -- appends to list
ALTER TYPE enum_type ADD VALUE 'new_value' BEFORE 'old_value';
ALTER TYPE enum_type ADD VALUE 'new_value' AFTER 'old_value';


답변

가능한 해결책은 다음과 같습니다. 전제 조건은 사용 된 열거 형 값에 충돌이없는 것입니다. (예를 들어 열거 형 값을 제거 할 때이 값을 더 이상 사용하지 않아야합니다.)

-- rename the old enum
alter type my_enum rename to my_enum__;
-- create the new enum
create type my_enum as enum ('value1', 'value2', 'value3');

-- alter all you enum columns
alter table my_table
  alter column my_column type my_enum using my_column::text::my_enum;

-- drop the old enum
drop type my_enum__;

또한 이런 방식으로 열 순서가 변경되지 않습니다.


답변

당신은 추가해야하는 상황에 빠질 경우 enum거래의 값을, FE가 이동 경로의 마이그레이션을 실행 ALTER TYPE당신이 얻을 오류가있을 것입니다 문 ERROR: ALTER TYPE ... ADD cannot run inside a transaction block(참조 이동 경로 문제 # 350 당신이로 같은 값을 추가 할 수 있습니다) pg_enum해결 방법으로 직접 ( type_egais_units대상의 이름입니다 enum) :

INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
    SELECT 'type_egais_units'::regtype::oid, 'NEW_ENUM_VALUE', ( SELECT MAX(enumsortorder) + 1 FROM pg_enum WHERE enumtypid = 'type_egais_units'::regtype )


답변

@Dariusz 보완 1

Rails 4.2.1에는 다음과 같은 문서 섹션이 있습니다.

== 트랜잭션 마이그레이션

데이터베이스 어댑터가 DDL 트랜잭션을 지원하면 모든 마이그레이션이 자동으로 트랜잭션으로 랩핑됩니다. 트랜잭션 내에서 실행할 수없는 쿼리가 있으며 이러한 상황에서는 자동 트랜잭션을 해제 할 수 있습니다.

class ChangeEnum < ActiveRecord::Migration
  disable_ddl_transaction!

  def up
    execute "ALTER TYPE model_size ADD VALUE 'new_value'"
  end
end


답변

Postgres 9.1 문서에서 :

ALTER TYPE name ADD VALUE new_enum_value [ { BEFORE | AFTER } existing_enum_value ]

예:

ALTER TYPE user_status ADD VALUE 'PROVISIONAL' AFTER 'NORMAL'


답변

면책 조항 : 이 솔루션을 시도하지 않았으므로 작동하지 않을 수 있습니다 😉

보고 있어야합니다 pg_enum. 기존 ENUM의 레이블 만 변경하려는 경우 간단한 UPDATE가 수행합니다.

새로운 ENUM 값을 추가하려면

  • 먼저 새 값을 pg_enum . 새 값이 마지막 값이어야한다면 끝났습니다.
  • 그렇지 않은 경우 (기존 값 사이에 새로운 ENUM 값이 필요함), 테이블에서 각각의 고유 한 값을 가장 높은 값에서 가장 낮은 값으로 업데이트해야합니다.
  • 그런 다음 pg_enum반대 순서 로 이름을 바꾸면됩니다 .

그림
당신은 라벨의 다음 세트를 가지고 :

ENUM ('enum1', 'enum2', 'enum3')

그리고 당신은 얻고 싶습니다 :

ENUM ('enum1', 'enum1b', 'enum2', 'enum3')

그때:

INSERT INTO pg_enum (OID, 'newenum3');
UPDATE TABLE SET enumvalue TO 'newenum3' WHERE enumvalue='enum3';
UPDATE TABLE SET enumvalue TO 'enum3' WHERE enumvalue='enum2';

그때:

UPDATE TABLE pg_enum SET name='enum1b' WHERE name='enum2' AND enumtypid=OID;

등등…