해당 글은 yo1dog blog의 내용을 번역한 한 글입니다.

원문

# 기존 타입을 변경하기
ALTER TYPE status_enum RENAME TO status_enum_old;

# 새로운 타입을 생성하기
CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');

# 새로운 타입으로 컬럼 변경하기
ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING job_status::text::status_enum;
# if you get an error, see bottom of post

# 타입 삭제하기
DROP TYPE status_enum_old;

PSQL은 사용자 타입을 추가하기 위해서 아래의 명령을 이용하여 쉽게 추가할 수 있다.

ALTER TYPE name ADD VALUE ...

불행히도(?), 9.6버전에서는 쉽게 수정하고, 쉽게 지우는 방법이 없다. ALTER TYPE name DROP/RENAME VALUE …

내가 찾은 가장 유명한 방법은 이 두가지중 하나였다.

0.1 지우고 새로 만들어라.

이 방법은 문제점은 타입이 사용중이라면, 좋지 않은 방법이다.

0.2 DELETE FROM pgenum…으로 그 시스템 테이블을 수정해라.

만들고자 하는 enum 값을 만들고, 바꾸고자 하는 값과 바꾸자. 이 방법은 기존 enum값을 지우지 않아도 되며, 다시 만들지 않아도 된다.

그리고 시스템 테이블을 수정하자. 하지만 조심해야 한다. 이 아이디어는 추천하지 않으며, 예측 불가능하기 때문이다.

1 샘플 시나리오

CREATE TYPE status_enum AS ENUM('queued', 'waiting', 'running', 'done');

CREATE TABLE job (
  id         int,
  job_status status_enum
);

INSERT INTO job VALUES
  (1, 'queued'),
  (2, 'waiting'),
  (3, 'running'),
  (4, 'done');

1.1 값 지우기

우리는 waiting 상태 값을 *running*값으로 설정할 것이다.

# 변경되어야 할 값을 새로운 값으로 설정한다.
UPDATE job SET job_status = 'running' WHERE job_status = 'waiting';

# 기존 enum 타입을 임시 타입으로 변경한다.
ALTER TYPE status_enum RENAME TO status_enum_old;

# 새로운 타입을 생성한다.
CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');

# 변경하고자 하는 컬럼을 새로운 타입으로 변경한다.
ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING status::text::status_enum;

# 만약 에러가 발생한다면, 아래의 글을 참조하자.

# 임시로 바꾼 enum타입을 삭제한다.
DROP TYPE status_enum_old;

1.2 값을 수정/이름 변경을 해보자

이렇게 가정해보자, waiting*값을 *blocked*값으로 리네이밍 하기를 원한다. 여기서 우리는 *blocked 값을 새로 넣고, 기존 *waiting*값을 지울것이다. 이 프로세스는 위와 비슷한 방법으로 진행될것이며, 기존의 타입에 새로운 값을 먼저 추가 할 것이다.

# 기존 타입에 새로운 값을 넣는다.
ALTER TYPE status_enum ADD VALUE 'blocked';

# 삭제하고자 하는 값을 새로운 값으로 변경하자.
UPDATE job SET job_status = 'blocked' WHERE job_status = 'waiting';

# 기존의 타입을 임시 타입으로 변경하자.
ALTER TYPE status_enum RENAME TO status_enum_old;

# 새로운 타입을 생성하자.
CREATE TYPE status_enum AS ENUM('queued', 'blocked', 'running', 'done');

# 새로운 타입으로 컬럼을 변경하자.
ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING status::text::status_enum;
# 만약 에러가 발생된다면, 아래의 글을 참조하자.

# 사용하지 않는 임시 타입을 삭제하자.
DROP TYPE status_enum_old;

1.3 에러들

  • invalid input value for enum {enum name}: "{some value}" 하나 또는 그이상의 값들이 새로 만들어진 타입의 값이 아닌 *{some value}*값을 갖는다.
  • default for column "{columnname}" cannot be cast automatically to type {enumname} 그 컬럼의 기본값, 그 컬럼은 새로 추가된 타입의 값이 아니다. 그 기본 값을 변경하거나, 지워야 한다.