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. - Como adicionar um índice exclusivo condicional no PostgreSQL
- Criar restrição exclusiva com colunas nulas
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:- Trigger vs. check constraint
- Como evitar uma dependência cíclica (referência circular) entre 3 tabelas?
- Desabilite todas as restrições e verificações de tabela ao restaurar um dump
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.