Como restringir uma tabela de banco de dados para que apenas uma linha possa ter um valor específico em uma coluna?

StackOverflow https://stackoverflow.com/questions/182262

  •  05-07-2019
  •  | 
  •  

Pergunta

Usando o Oracle, se um valor de coluna puder ser 'sim' ou 'não', é possível restringir uma tabela para que apenas uma linha possa ter um valor 'sim'?

Prefiro redesenhar a estrutura da tabela, mas isso não é possível.

Infelizmente, os valores nulos não são permitidos nesta tabela.

Foi útil?

Solução

Use um índice baseado em função:

create unique index only_one_yes on mytable
(case when col='YES' then 'YES' end);

O Oracle apenas indexa as teclas que não são completamente nulas, e a expressão do caso aqui garante que todos os valores 'não' sejam alterados para nulos e, portanto, não indexados.

Outras dicas

Este é um hack de Kludgy, mas se a coluna permitir nulo, você poderá usar o NULL no lugar de "não" e usar "sim", assim como antes. Aplique uma restrição -chave única a essa coluna e você nunca receberá dois valores "sim", mas ainda terá muitos nos.

ATUALIZAÇÃO: @Nick PierPoint: sugeriu adicionar uma restrição de verificação para que os valores da coluna sejam restritos a apenas "sim" e nulo. A sintaxe é eliminada em sua resposta.

Você vai querer verificar um artigo de Tom Kyte com exatamente esta pergunta sendo feita e sua resposta:

http://tkyte.blogspot.com/2008/05/another-oty.html

Resumo: Não use gatilhos, não use transações autônomas, use duas tabelas.

Se você usar um banco de dados Oracle, deve saber Asktom e pegue seus livros.

Não funciona na definição da tabela.

No entanto, se você atualizar a tabela usando um gatilho chamando um procedimento armazenado, poderá garantir que apenas uma linha contenha "sim".

  1. Defina todas as linhas como "não"
  2. Defina a linha que você deseja sim

Seguindo do meu comentário para uma resposta anterior de Yukondude, eu adicionaria um índice exclusivo e uma restrição de cheque:

create table mytest (
    yesorno varchar2(3 char)
);

create unique index uk_mytest_yesorno on mytest(yesorno);

alter table mytest add constraint ck_mytest_yesorno check (yesorno is null or yesorno = 'YES');

O Oracle apoia algo como índices filtrados (Na semana passada, ouvi dizer que, por exemplo, msql2008)? Talvez você possa definir um Chave única que se aplica apenas a linhas com o valor "Sim" em sua coluna.

Acho que usaria uma segunda tabela para apontar para a linha apropriada na sua tabela atual. Essa outra tabela também pode ser usada para armazenar valores de outras variáveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top