ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

PostgreSQL と H2 Database の両方で使える SEQUENCE 値生成方法 (MySQL の AUTO_INCREMENT 的なやつ)

SQL DB に新しい行を挿入したときに自動的に ID 値を生成して欲しいことはままある。 このような処理をしてくれるテーブル定義についての話。

MySQL だと AUTO_INCREMENT を使いがち

MySQL を使ってる場合は AUTO_INCREMENT で済ませちゃうことが多い (H2 Database でも使用可)。

CREATE TABLE "foo" (
  "id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
);

PostgreSQL のための AUTO_INCREMENT 以外の方法

ただ、PostgreSQL では AUTO_INCREMENT が使えない。 代わりに使える方法を 2 つ書いておく。

BIGSERIAL 型を使う

PostgreSQL で、テーブル定義時に型として BIGSERIAL 型を使用すると内部的に SEQUENCE を利用するようになる。

The data types smallserial, serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying:

CREATE TABLE tablename (
    colname SERIAL
);

is equivalent to specifying:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
PostgreSQL: Documentation: 10: 8.1. Numeric Types

上の例では SERIAL 型が使われているが、これは INTEGER 相当なので、BIGINT 相当のサイズにしたければ BIGSERIAL を使用すること。

ちなみに BIGSERIAL は H2 Database でも使用できる (ちゃんとしたドキュメントは見当たらなかった)。 MySQL でも SERIAL は使用できる (MySQL の場合は SERIALBIGINT になる) が、BIGSERIAL は使えない (MySQL 8.0 で検証)。

外部 SEQUENCE 生成子を使う

標準 SQL に従った方法はこれっぽい。 上の SERIAL 型を使った場合と等価な例に載っているような形になる。 ただ、H2 Database は SEQUENCE の所有カラムを明示できないようなので、そこは指定しないでおく。 (H2 Database でも使いたいので。)

CREATE SEQUENCE "foo_id_seq";
CREATE TABLE "foo" (
    "id" bigint NOT NULL DEFAULT nextval('foo_id_seq')
);