Ponieważ PRIMARY KEY produkuje dołączone kolumny NOT NULL automatycznie . Cytuję instrukcję tutaj:
Ograniczenie klucza podstawowego określa, że kolumna lub kolumny atable mogą zawierać tylko unikalne (nie zduplikowane) wartości inne niż null.Technicznie PRIMARY KEY jest tylko kombinacją UNIQUE i NOT NULL .
Pogrubiony nacisk na moje.
Przeprowadziłem test, aby potwierdzić, że NOT NULL jest całkowicie nadmiarowy w połączeniu z PRIMARY KEY ograniczenie (w obecnej implementacji, ponownie przetestowane w wersji 13). NOT NULL ograniczenie pozostaje nawet po usunięciu ograniczenia PK, niezależnie od jawnego NOT NULL klauzula w czasie tworzenia.
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<>graj tutaj
Identyczne zachowanie, jeśli NULL znajduje się w CREATE TABLE oświadczenie.
Nadal nie zaszkodzi zachować NOT NULL nadmiarowo w repozytoriach kodu, jeśli kolumna ma być NOT NULL . Jeśli później zdecydujesz się zmienić ograniczenie PK, możesz zapomnieć o zaznaczeniu kolumny NOT NULL - czy w ogóle miał być NOT NULL .
W wiki Postgres TODO znajduje się element, który umożliwia rozdzielenie NOT NULL z ograniczenia PK. Może się to zmienić w przyszłych wersjach:
Przenieś informacje o ograniczeniu NOT NULL do pg_constraint
Obecnie ograniczenia NOT NULL są przechowywane w pg_attribute bez podania ich pochodzenia, np. klucze podstawowe. Jednym z przejawów problemu jest to, że usunięcie ograniczenia KLUCZ PODSTAWOWY nie powoduje usunięcia oznaczenia ograniczenia NOT NULL. Inną kwestią jest to, że powinniśmy prawdopodobnie wymusić propagowanie wartości NOT NULL z tabel nadrzędnych do dzieci, tak jak w przypadku ograniczeń CHECK. (Ale czy porzucenie PRIMARY KEY wpływa na dzieci?)
Odpowiedź na dodane pytanie
Czy nie byłoby lepiej, gdyby ta wewnętrznie sprzeczna CREATE TABLE po prostu zawiodła?
Jak wyjaśniono powyżej, to
foo_id INTEGER NULL PRIMARY KEY
jest (obecnie) w 100% odpowiednikiem:
foo_id INTEGER PRIMARY KEY
Od NULL jest traktowane jako słowo szumu w tym kontekście.
I nie chcielibyśmy, aby to drugie zawiodło. Więc to nie jest opcja.