PostgreSQL에서의 일련번호 처리

PostgreSQL에서의 일련번호 처리
자료 구조를 짤 때, 추상화된 일련 번호를 많이 사용합니다.
이 글은 PostgreSQL에 그 일련 번호 처리를 어떻게 하는지 살펴보는 사용자용 토막글입니다.
시퀀스 개체
PostgreSQL에서는 전통적으로 어떤 숫자를 차례대로 사용할 경우, 시퀀스 SEQUENCE 라는 개체를 사용했습니다.
ioseph=> CREATE SEQUENCE seq; CREATE SEQUENCE ioseph=> select nextval('seq'); nextval --------- 1 (1개 행) ioseph=> select nextval('seq'); nextval --------- 2 (1개 행)
저렇게 만들고, 저렇게 사용합니다.
응용하면, 테이블을 만들 때, 칼럼의 default 속성에 이것을 사용하면, 기본키가 일련번호인 테이블을 만들 수 있습니다.
ioseph=> CREATE TABLE t ( pk integer NOT NULL DEFAULT nextval('seq'), data text); CREATE TABLE ioseph=> INSERT INTO t VALUES (default, 'a'); INSERT 0 1 ioseph=> SELECT * FROM t; pk | data ----+------ 3 | a (1개 행)
SERIAL 자료형
위 시퀀스 개체를 사용하는 경우, 몇 가지 불편한 점이 있습니다. 미리 시퀀스를 만들어야 하며, 테이블을 만들 때, 긴 칼럼 정의를 해야하고, 테이블을 지울 때, 시퀀스도 따로 지워야 합니다. 이런 불편함을 해결 하기 위에서 PostgreSQL에서는 serial 이라는 자료형을 제공합니다.
ioseph=> DROP TABLE t; DROP TABLE ioseph=> DROP SEQUENCE seq; DROP SEQUENCE ioseph=> CREATE TABLE t ( pk serial, data text); CREATE TABLE ioseph=> INSERT INTO t VALUES (default, 'a'); INSERT 0 1 ioseph=> INSERT INTO t VALUES (default, 'a'); INSERT 0 1 ioseph=> SELECT * FROM t; pk | data ----+------ 1 | a 2 | a (2개 행) ioseph=> \d t "public.t" 테이블 필드명 | 종류 | Collation | NULL허용 | 초기값 --------+---------+-----------+----------+------------------------------- pk | integer | | not null | nextval('t_pk_seq'::regclass) data | text | | | ioseph=> \ds t_pk_seq 릴레이션(relation) 목록 스키마 | 이름 | 종류 | 소유주 --------+----------+--------+-------- public | t_pk_seq | 시퀀스 | ioseph (1개 행) ioseph=> DROP TABLE t; DROP TABLE ioseph=> \ds t_pk_seq "t_pk_seq" 이름을 릴레이션(relation) 없음.
이렇게 독립된 시퀀스 개체를 이용하는 방법보다 간단하고, 테이블 삭제 때 신경 쓸 부분이 적습니다.
GENERATED ALWAYS AS IDENTITY
그런데, 이 serial 자료형을 사용하는 일련 번호 처리는 표준 SQL이 아닙니다. ANSI SQL 2003 규약은 이 일련 번호 처리를 위한 구문으로
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
이런 형태를 사용하자고 제안했습니다.
그래서, PostgreSQL 11 버전부터 이 구문을 지원합니다.
ioseph=> CREATE TABLE t ( pk integer GENERATED ALWAYS AS IDENTITY, data text); CREATE TABLE ioseph=> INSERT INTO t VALUES (default, 'a'); INSERT 0 1 ioseph=> INSERT INTO t VALUES (default, 'a'); INSERT 0 1 ioseph=> SELECT * FROM t; pk | data ----+------ 1 | a 2 | a (2개 행)
위 구문에서 always 와, by default 차이는 스스로 공부하시고.