SQL では,NULLに比較述語を適用すると,常にunknownになります.これは分かりにくい印象がありますが,3値論理に準拠すれば明らかです.
この性質により,例えば Django で以下のように apple_id
に unique
と null
が共存できます.ここで,apple_id
は必須ではないけれども他のりんごとは重複しない数値のことです.
from django.db import models class Apple(models.Model): apple_id = models.IntegerField(unique=True, null=True)
なお,以下の環境で動作確認をしました.
PostgreSQL 15.1 (Debian 15.1-1.pgdg110+1) on x86_64-pc-linux-gnu Django==4.1.3 psycopg2==2.9.5
これの unittest は以下のようになり,実行すると成功します.
from django.db.utils import IntegrityError from django.test import TransactionTestCase from .models import Apple class AppleTest(TransactionTestCase): def test_unique_field(self): with self.assertRaises(IntegrityError): Apple.objects.create(apple_id=1) Apple.objects.create(apple_id=1) self.assertEqual(Apple.objects.count(), 1) def test_unique_and_null_field(self): Apple.objects.create(apple_id=None) Apple.objects.create(apple_id=None) self.assertEqual(Apple.objects.count(), 2)
Found 2 test(s). Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.165s OK
apple_id
が NULL な Apple が複数存在しても,NULL = NULL は unknown なので,unique に違反しないためです.