PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pourquoi puis-je créer une table avec PRIMARY KEY sur une colonne nullable ?

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 de UNIQUE et NOT 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.