PostgreSQL дозволяє створити власний перелічуваний тип:
CREATE TYPE order_status AS ENUM ('new', 'paid', 'shipped', 'cancelled');
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
status order_status NOT NULL DEFAULT 'new'
);
Плюси: компактне зберігання (4 байти), перевірка значень базою, сортування в порядку оголошення.
Мінуси, через які його часто уникають:
- Додати значення можна (
ALTER TYPE order_status ADD VALUE 'refunded' AFTER 'paid'), а от видалити - ні. Доведеться створити новий тип, перенести колонку й видалити старий - на великій таблиці це переписування даних. ADD VALUEдо PostgreSQL 12 не можна було виконати в транзакції - міграції ламалися.- Тип - окремий об'єкт схеми: його треба створювати до таблиці, переносити між базами, враховувати в міграціях. ORM підтримують його гірше, ніж звичайні колонки.
Альтернатива 1 - text з CHECK:
status text NOT NULL DEFAULT 'new'
CHECK (status IN ('new', 'paid', 'shipped', 'cancelled'))
Змінити перелік - замінити обмеження (NOT VALID + VALIDATE для великих таблиць), без зміни типу колонки. У Laravel так працює $table->enum() на PostgreSQL.
Альтернатива 2 - таблиця-довідник із зовнішнім ключем: коли значень багато, вони змінюються адміністраторами, або в них є атрибути (назва для показу, колір, порядок, чи активний).
Як обирати:
- Перелік стабільний і короткий, змінюється лише з кодом -
CHECKабо нативний enum. - Перелік змінюється без деплою чи має атрибути - довідник.
- Логіка значень живе в застосунку - PHP enum для коду плюс
CHECKу базі для цілісності.