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

Adicionar restrição para tornar a coluna única por grupo de linhas


Curta @lad2025 comentou , status deve ser boolean . Mais barato, mais limpo.

De qualquer forma, você pode impor sua regra com um índice exclusivo parcial :

Para permitir zero ou uma linha com status = 'Active' em toda a tabela :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';

Para permitir zero ou uma linha com status = 'Active' por userid , faça userid a coluna indexada:
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';

Observe que userid IS NULL não acionaria violações exclusivas, porque dois valores NULL nunca são considerados iguais. userid deve ser definido NOT NULL nesse caso.

Por que indexar e não restringir?


Abordando seu pergunta no comentário :Este é um índice, não um CONSTRAINT .

O índice para o primeiro caso é pequeno , contendo uma ou nenhuma linha.
O índice para o segundo caso contém uma linha por userid existente , mas é a maneira mais barata e rápida , além de ser limpo e seguro. Você precisaria de um índice para verificar outras linhas em qualquer caso para tornar isso rápido.

Você não pode ter um CHECK verificação de restrição em outras linhas - pelo menos não de maneira limpa e confiável. Existem maneiras que eu certamente não recomendaria para este caso:

Se você usar um UNIQUE restrição em (userid, status) (que também é implementado com um índice exclusivo em segundo plano!), você não pode torná-lo parcial e todos as combinações são impostas para serem únicas. Você poderia ainda use isso se você trabalha com status IS NULL para todos os casos, exceto o 'Active' caso. Mas isso na verdade imporia um índice muito maior, incluindo todos linhas.