Parce que la PRIMARY KEY
fait la ou les colonnes incluses NOT NULL
automatiquement . Je cite le manuel ici :
La contrainte de clé primaire spécifie qu'une ou plusieurs colonnes d'une table ne peuvent contenir que des valeurs uniques (non dupliquées) et non nulles. Techniquement,
PRIMARY KEY
est simplement une combinaison deUNIQUE
etNOT NULL
.
J'insiste sur moi.
J'ai exécuté un test pour confirmer que NOT NULL
est complètement redondant en combinaison avec une PRIMARY KEY
contrainte (dans l'implémentation actuelle, retestée en version 13). Le NOT NULL
la contrainte reste même après avoir supprimé la contrainte PK, indépendamment d'un NOT NULL
explicite clause au moment de la création.
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<>jouez ici
Comportement identique si NULL
est inclus dans le CREATE TABLE
déclaration.
Cela ne fera toujours pas de mal de garder NOT NULL
de manière redondante dans les référentiels de code si la colonne est censée être NOT NULL
. Si vous décidez ultérieurement de modifier la contrainte PK, vous risquez d'oublier de marquer la colonne NOT NULL
- ou s'il était même censé être NOT NULL
.
Il y a un élément dans le wiki Postgres TODO pour découpler NOT NULL
de la contrainte PK. Cela pourrait donc changer dans les futures versions :
Déplacer les informations de contrainte NOT NULL vers pg_constraint
Actuellement, les contraintes NOT NULL sont stockées dans pg_attribute sans aucune désignation de leurs origines, par ex. clés primaires. Un problème manifeste est que la suppression d'une contrainte PRIMARY KEY ne supprime pas la désignation de contrainte NOT NULL. Un autre problème est que nous devrions probablement forcer la propagation de NOT NULL des tables parents aux enfants, tout comme le sont les contraintes CHECK. (Mais est-ce que laisser tomber PRIMARY KEY affecte les enfants ?)
Réponse à la question ajoutée
Ne serait-il pas préférable que ce CREATE TABLE contradictoire échoue juste là ?
Comme expliqué ci-dessus, cela
foo_id INTEGER NULL PRIMARY KEY
est (actuellement) 100 % équivalent à :
foo_id INTEGER PRIMARY KEY
Depuis NULL
est traité comme un mot parasite dans ce contexte.
Et nous ne voudrions pas que ce dernier échoue. Ce n'est donc pas une option.