Postgresの一意のインデックスは、等しい値に基づいています 、ただし、NULLは、他のNULLを含め、何にも等しくなることはありません。したがって、deleted_at値がNULLの行は、他の可能な行とは異なります。したがって、任意の数の行を挿入できます。
これを回避する1つの方法は、部分インデックスを作成することです。 、NULLのある行とない行に異なるルールを適用する:
CREATE UNIQUE INDEX ... ON subscriptions
(user_id, class_type_id) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX ... ON subscriptions
(user_id, class_type_id, deleted_at) WHERE deleted_at IS NOT NULL;