Campo Booleano no Oracle


145

Ontem, eu queria adicionar um campo booleano a uma tabela Oracle. No entanto, não há realmente um tipo de dados booleano no Oracle. Alguém aqui sabe a melhor maneira de simular um booleano? Pesquisando no assunto, descobrimos várias abordagens

  1. Use um número inteiro e não se preocupe em atribuir nada além de 0 ou 1 a ele.

  2. Use um campo char com 'Y' ou 'N' como os únicos dois valores.

  3. Use uma enumeração com a restrição CHECK.

Os desenvolvedores Oracle experientes sabem qual abordagem é preferida / canônica?


195
Eu gostaria que o Oracle tivesse um walltipo de dados para poder esmagar minha cabeça ao usar booleanos.
— Greg

Respostas:


82

Achei este link útil.

Aqui está o parágrafo destacando alguns dos prós / contras de cada abordagem.

O design mais comum é imitar os muitos sinalizadores booleanos que as visualizações do dicionário de dados da Oracle usam, selecionando 'Y' para verdadeiro e 'N' para falso. No entanto, para interagir corretamente com ambientes host, como JDBC, OCCI e outros ambientes de programação, é melhor selecionar 0 para false e 1 para true para que ele funcione corretamente com as funções getBoolean e setBoolean.

Basicamente, eles defendem o método número 2, por uma questão de eficiência, usando

  • valores de 0/1 (devido à interoperabilidade com JDBC, getBoolean()etc.) com uma restrição de verificação
  • um tipo de CHAR (porque usa menos espaço que NUMBER).

O exemplo deles:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`

31
Aconselho não usar 'N' e 'Y', pois depende do idioma. Os anglófonos às vezes esquecem que a maior parte do mundo não representa o conceito de verdade com a letra Y. Por outro lado, o significado de 0 e 1 é constante através das barreiras linguísticas.
— Andrew Spencer

7
0 e 1 como valores booleanos não são consistentes na ciência da computação - as linguagens do tipo shell script tendem a ter 0 como sucesso e diferente de zero como falha, enquanto as linguagens do tipo C tendem a ter 0 como falha e diferente de zero como sucesso.
— Phil

41
Como valores booleanos , eles não são ambíguos. Os códigos de retorno do processo não são valores booleanos.
— Andrew Spencer

13
Por que esse parágrafo inteiro do link fornecido foi ignorado nesta resposta? "O design mais comum é imitar os muitos sinalizadores booleanos que as visualizações do dicionário de dados da Oracle usam, selecionando 'Y' para verdadeiro e 'N' para falso. No entanto, para interagir corretamente com ambientes de host, como JDBC, OCCI, e outros ambientes de programação, é melhor selecionar 0 para false e 1 para true para que ele funcione corretamente com as funções getBoolean e setBoolean. " Eles afirmam que, embora 'S / N' seja comum, é recomendável usar '0/1' para aumentar a compatibilidade com ambientes host.
— Justin.hughey

28

O próprio Oracle usa Y / N para valores booleanos. Para completar, deve-se notar que o pl / sql tem um tipo booleano, são apenas as tabelas que não.

Se você estiver usando o campo para indicar se o registro precisa ser processado ou não, considere usar Y e NULL como valores. Isso cria um índice muito pequeno (leia rapidamente) que ocupa muito pouco espaço.


7
+1 Bom argumento sobre as visualizações e tabelas internas do Oracle usando Y / N. Se a Oracle fizer dessa maneira, deve estar certo! :)
— Jeffrey Kemp

Você pode explicar como Y e NULL fazem um pequeno índice em comparação com Y e N?
— styfle

6
NULLs não são indexados no Oracle, portanto, se seu índice contiver alguns caracteres Y, mas principalmente NULLs, você terá um índice muito pequeno.
— Leigh Riffel

25

Para usar a menor quantidade de espaço, você deve usar um campo CHAR restrito a 'Y' ou 'N'. O Oracle não suporta os tipos de dados BOOLEAN, BIT ou TINYINT, portanto, um byte de CHAR é o menor possível.


19

A melhor opção é 0 e 1 (como números - outra resposta sugere 0 e 1 como CHAR para eficiência de espaço, mas isso é um pouco distorcido para mim), usando NOT NULL e uma restrição de verificação para limitar o conteúdo a esses valores. (Se você precisa que a coluna seja anulável, não é um booleano com o qual você está lidando, mas uma enumeração com três valores ...)

Vantagens de 0/1:

  • Linguagem independente. 'Y' e 'N' ficariam bem se todos usassem. Mas eles não. Na França, eles usam 'O' e 'N' (eu já vi isso com meus próprios olhos). Não programei na Finlândia para ver se eles usam 'E' e 'K' lá - sem dúvida, são mais espertos do que isso, mas você não pode ter certeza.
  • Congruente com a prática em linguagens de programação amplamente usadas (C, C ++, Perl, Javascript)
  • Joga melhor com a camada de aplicação, por exemplo, Hibernate
  • Leva a SQL mais sucinto, por exemplo, para descobrir quantas bananas estão prontas para comer em select sum(is_ripe) from bananasvez de select count(*) from bananas where is_ripe = 'Y'ou mesmo (yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Vantagens de 'Y' / 'N':

  • Ocupa menos espaço que 0/1
  • É o que a Oracle sugere, então pode ser o que algumas pessoas estão mais acostumadas

Outro pôster sugeria 'Y' / nulo para ganhos de desempenho. Se você provou que precisa do desempenho, é justo o suficiente, mas evite, pois isso torna a consulta menos natural (em some_column is nullvez de some_column = 0) e em uma junção esquerda, você confundirá a falsidade com registros inexistentes.


3
Você acha que hoje em dia muitos booleanos são TriState, isto é, verdadeiro, falso e desconhecido. o que se encaixa perfeitamente com a idéia nula do banco de dados. simplesmente porque um monte de vezes, sabendo nenhuma resposta foi dada é de vital importância
— miket

1
Sim, verdadeiro-falso-desconhecido pode ser necessário, embora se eu fosse exigente (o que sou), diria que não deveria ser descrito como um booleano, porque não é.
— Andrew Spencer

2
se você for tão exigente, poderá argumentar o mesmo para todos os tipos de dados. como em definição estrita número inteiro, duplo (acho que devo dizer que o comprimento duplo aumenta o ponto flutuante), binário, string etc. todos assumem que um valor é fornecido, mas as implementações de banco de dados sempre adicionam uma opção de valor nulo Boolean não é diferente
— MikeT

1
true, em uma observação positiva para o seu método, se você configurar seu número corretamente, ele também poderá ser armazenado no mesmo byte de um campo char, que anula o argumento de tamanho contra o uso de 0/1, não consigo encontrar o link atualmente, mas armazenamento de um número varia de 1 - 22 bytes, dependendo da configuração
— miket

4
Suspeito que os votos negativos se devam a um ponto de vista herdado na escolha da implementação com mais eficiência de memória. Essa eficiência de memória dos dias de hoje é muito menos prioritária e deve ser levada em consideração após a usabilidade e a compatibilidade. Para qualquer pessoa que possa responder a esse comentário, recomendo ler sobre otimização prematura. É exatamente isso que ocorre ao escolher 'S / N' puramente com base na eficiência da memória. Você está perdendo a compatibilidade nativa com um conjunto de estruturas comumente usadas por causa dessa decisão.
— Justin.hughey

5

1/0 ou Y / N com uma restrição de verificação. éter é bom. Pessoalmente, prefiro 1/0, pois faço muito trabalho em perl, e isso facilita muito a operação booleana de perl nos campos do banco de dados.

Se você quiser uma discussão realmente aprofundada dessa questão com um dos honchos do Oracles, confira o que Tom Kyte tem a dizer sobre isso. Aqui


1/0 é dito ser "menos eficiente de memória", mas ... eu gosto mais também (e hibernar aparentemente requer 1/0 para um booleano)
— rogerdpack

1/0 é o padrão do Hibernate para um booleano, mas você pode definir qualquer mapeamento personalizado que desejar.
— Andrew Spencer

@rogerdpack eis porque um campo char é um byte, ou 2 bytes para nchar, enquanto que, dependendo como é definido um número pode ser de 1 a 22 bytes
— miket

4

O banco de dados em que fiz a maior parte do meu trabalho usou 'Y' / 'N' como booleanos. Com essa implementação, você pode executar alguns truques como:

  1. Contar linhas verdadeiras:
    SELECT SUM (CASE WHEN BOOLEAN_FLAG = 'Y' THEN 1 ELSE 0 0) FROM X

  2. Ao agrupar linhas, aplique a lógica "Se uma linha for verdadeira, todas serão verdadeiras":
    SELECT MAX (BOOLEAN_FLAG) FROM Y
    Por outro lado, use MIN para forçar o agrupamento false se uma linha for falsa.


4
de fato, os exemplos mostrados também são úteis para a abordagem 0/1 - e, IMHO, mais rápido.
— igorsantos07

2

Um exemplo de trabalho para implementar a resposta aceita adicionando uma coluna "Boolean" a uma tabela existente em um banco de dados oracle (usando o numbertipo):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

Isso cria uma nova coluna my_table_namechamada my_new_boolean_columncom valores padrão de 0. A coluna não aceita NULLvalores e restringe os valores aceitos a0 ou 1.


1

Em nossos bancos de dados, usamos uma enumeração que garante que passamos TRUE ou FALSE. Se você fizer uma das duas primeiras maneiras, é muito fácil começar a adicionar novo significado ao número inteiro sem passar por um design adequado ou terminar com esse campo char com Y, y, N, n, T, t, Valores F, f e ter que lembrar qual seção do código usa qual tabela e qual versão de true está usando.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.