Protože PRIMARY KEY dělá zahrnuté sloupce NOT NULL automaticky . Zde cituji manuál:
Omezení primárního klíče určuje, že sloupec nebo sloupce tabulky mohou obsahovat pouze jedinečné (neduplicitní), nenulové hodnoty. Technicky
PRIMARY KEYje pouze kombinacíUNIQUEaNOT NULL.
Tučné zdůraznění moje.
Provedl jsem test, abych potvrdil, že NOT NULL je v kombinaci s PRIMARY KEY zcela redundantní omezení (v aktuální implementaci, znovu testováno ve verzi 13). NOT NULL omezení zůstává i po zrušení omezení PK, bez ohledu na explicitní NOT NULL doložka v době vytvoření.
CREATE TABLE foo (foo_id int PRIMARY KEY);
ALTER TABLE foo DROP CONSTRAINT foo_pkey;
db=# \d foo
table »public.foo«
column | type | attribute
--------+---------+-----------
foo_id | integer | not null -- stays
db<>zde hrajte
Identické chování, pokud NULL je součástí CREATE TABLE prohlášení.
Stále nebude na škodu ponechat NOT NULL redundantně v úložištích kódu, pokud má být sloupec NOT NULL . Pokud se později rozhodnete změnit omezení PK, možná zapomenete označit sloupec NOT NULL - nebo zda to dokonce mělo být NOT NULL .
Ve wiki Postgres TODO je položka k oddělení NOT NULL z omezení PK. To se tedy může v budoucích verzích změnit:
Přesuňte informace o omezení NOT NULL do pg_constraint
V současné době jsou omezení NOT NULL uložena v pg_attribute bez jakéhokoli označení jejich původu, např. primární klíče. Jedním z zjevných problémů je, že zrušením omezení PRIMARY KEY se neodstraní označení omezení NOT NULL. Dalším problémem je, že bychom pravděpodobně měli vynutit šíření NOT NULL z rodičovských tabulek dětem, stejně jako omezení CHECK. (Ovlivňuje však vypuštění PRIMARY KEY děti?)
Odpověď na přidanou otázku
Nebylo by lepší, kdyby tato protichůdná CREATE TABLE právě tam selhala?
Jak je vysvětleno výše, toto
foo_id INTEGER NULL PRIMARY KEY
je (aktuálně) 100 % ekvivalentní:
foo_id INTEGER PRIMARY KEY
Od NULL je v tomto kontextu považováno za šumové slovo.
A my bychom nechtěli, aby to druhé selhalo. Takže toto není možnost.