8.7. 列挙型

列挙(enum)型は静的、事前に定義された値の、順序付き集合からなるデータ型です。 これは、多くのプログラミング言語におけるenum型と同じです。 列挙型の例として、曜日や個々のデータについてのステータス値の集合が挙げられます。

8.7.1. 列挙型の宣言

列挙型はCREATE TYPEコマンドを使用して作成されます。 以下に例を示します。

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

作成後、他のデータ型とほとんど同じように、列挙型をテーブルや関数定義で使用することができます。

例 8-3. 基本的な列挙型の使用方法

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
CREATE TABLE person (
    name text,
    current_mood mood
);
INSERT INTO person VALUES ('Moe', 'happy');
SELECT * FROM person WHERE current_mood = 'happy';
 name | current_mood 
------+--------------
 Moe  | happy
(1 row)

8.7.2. 順序

列挙型内の値の順序はその型を宣言した時に値を列挙した順番になります。 列挙型に対して、すべての比較演算子と関連する集約関数がサポートされます。 以下に例を示します。

例 8-4. 列挙型の順序

INSERT INTO person VALUES ('Larry', 'sad');
INSERT INTO person VALUES ('Curly', 'ok');
SELECT * FROM person WHERE current_mood > 'sad';
 name  | current_mood 
-------+--------------
 Moe   | happy
 Curly | ok
(2 rows)

SELECT * FROM person WHERE current_mood > 'sad' ORDER BY current_mood;
 name  | current_mood 
-------+--------------
 Curly | ok
 Moe   | happy
(2 rows)

SELECT name FROM person
  WHERE current_mood = (SELECT MIN(current_mood) FROM person);
 name  
-------
 Larry
(1 row)

8.7.3. 型の安全性

列挙型は完全にデータ型と分かれており、互いに比較することはできません。

例 8-5. キャストの欠落

CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
CREATE TABLE holidays (                                           
    num_weeks int,
    happiness happiness
);
INSERT INTO holidays(num_weeks,happiness) VALUES (4, 'happy');
INSERT INTO holidays(num_weeks,happiness) VALUES (6, 'very happy');
INSERT INTO holidays(num_weeks,happiness) VALUES (8, 'ecstatic');
INSERT INTO holidays(num_weeks,happiness) VALUES (2, 'sad');
ERROR:  invalid input value for enum happiness: "sad"
SELECT person.name, holidays.num_weeks FROM person, holidays
  WHERE person.current_mood = holidays.happiness;
ERROR:  operator does not exist: mood = happiness

もし本当に上のようなことが必要ならば、独自の演算子を作成するか、問い合わせに明示的なキャストを付けることで行うことができます。

例 8-6. テキスト型にキャストすることによる異なる列挙型を比較

SELECT person.name, holidays.num_weeks FROM person, holidays
  WHERE person.current_mood::text = holidays.happiness::text;
 name | num_weeks 
------+-----------
 Moe  |         4
(1 row)

8.7.4. 実装の詳細

列挙型の値はディスク上では4バイトを占めます。 列挙型の値のテキストラベルの長さは、PostgreSQLに組み込まれたNAMEDATALEN設定により制限されます。 標準の構築では、これはおよそ63バイトを意味します。

列挙型のラベルでは大文字小文字を区別します。 このため'happy''HAPPY'と同じではありません。 ラベル内の空白文字も意味を持ちます。