PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Por que posso criar uma tabela com PRIMARY KEY em uma coluna anulável?


Porque a PRIMARY KEY faz as colunas incluídas NOT NULL automaticamente . Cito o manual aqui:

A restrição de chave primária especifica que uma coluna ou colunas de uma tabela podem conter apenas valores exclusivos (não duplicados) não nulos. Tecnicamente, PRIMARY KEY é apenas uma combinação de UNIQUE e NOT NULL .

Minha ênfase em negrito.

Fiz um teste para confirmar que NOT NULL é completamente redundante em combinação com uma PRIMARY KEY restrição (na implementação atual, testada novamente na versão 13). O NOT NULL restrição permanece mesmo depois de descartar a restrição PK, independentemente de um NOT NULL explícito cláusula no momento da criação.
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<>mexa aqui

Comportamento idêntico se NULL está incluído no CREATE TABLE demonstração.

Ainda não fará mal manter NOT NULL redundantemente em repositórios de código se a coluna deve ser NOT NULL . Se mais tarde você decidir alterar a restrição PK, pode esquecer de marcar a coluna NOT NULL - ou se deveria ser NOT NULL .

Existe um item no wiki do Postgres TODO para desacoplar NOT NULL da restrição PK. Portanto, isso pode mudar em versões futuras:

Mover as informações de restrição NOT NULL para pg_constraint

Atualmente as restrições NOT NULL são armazenadas em pg_attribute sem qualquer designação de suas origens, por exemplo. chaves primárias. Um problema de manifesto é que descartar uma restrição PRIMARY KEY não remove a designação de restrição NOT NULL. Outra questão é que provavelmente devemos forçar NOT NULL a ser propagado de tabelas pai para filhas, assim como as restrições CHECK. (Mas então largar a CHAVE PRIMÁRIA afeta as crianças?)

Resposta à pergunta adicionada


Não seria melhor se esse CREATE TABLE autocontraditório simplesmente falhasse ali mesmo?

Como explicado acima, este
foo_id INTEGER NULL PRIMARY KEY

é (atualmente) 100% equivalente a:
foo_id INTEGER PRIMARY KEY

Desde NULL é tratado como palavra de ruído neste contexto.
E não queremos que o último falhe. Portanto, esta não é uma opção.