Campo booleano in Oracle


145

Ieri volevo aggiungere un campo booleano a una tabella Oracle. Tuttavia, in Oracle non esiste un tipo di dati booleano. Qualcuno qui conosce il modo migliore per simulare un booleano? Googling il soggetto ha scoperto diversi approcci

  1. Usa un numero intero e non preoccuparti di assegnargli nulla diverso da 0 o 1.

  2. Utilizzare un campo char con 'Y' o 'N' come unici due valori.

  3. Utilizzare un enum con il vincolo CHECK.

Gli sviluppatori Oracle esperti sanno quale approccio è preferito / canonico?


195
Vorrei che Oracle avesse un walltipo di dati in modo da potermi sbattere la testa contro usando booleani.
Greg

Risposte:


82

Ho trovato utile questo link.

Ecco il paragrafo che evidenzia alcuni dei pro / contro di ogni approccio.

Il design più comunemente visto è quello di imitare i numerosi flag simili a booleani utilizzati dalle viste del dizionario dei dati di Oracle, selezionando "Y" per true e "N" per false. Tuttavia, per interagire correttamente con ambienti host, come JDBC, OCCI e altri ambienti di programmazione, è meglio selezionare 0 per false e 1 per true in modo che possa funzionare correttamente con le funzioni getBoolean e setBoolean.

Fondamentalmente sostengono il metodo numero 2, per motivi di efficienza, usando

  • valori di 0/1 (a causa dell'interoperabilità con JDBC getBoolean()ecc.) con un vincolo di controllo
  • un tipo di CHAR (perché utilizza meno spazio di NUMBER).

Il loro esempio:

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

31
Sconsiglio di usare 'N' e 'Y' poiché dipende dalla lingua. Gli anglofoni a volte dimenticano che la maggior parte del mondo non rappresenta il concetto di verità con la lettera Y. Al contrario, il significato di 0 e 1 è costante attraverso le barriere linguistiche.
Andrew Spencer,

7
0 e 1 come valori booleani non sono coerenti con l'informatica - i linguaggi di tipo script di shell tendono ad avere 0 come successo, e diversi da zero come fallimento, mentre i linguaggi di tipo C tendono ad avere 0 come fallimento e diversi da zero come successo.
Phil

41
Come valori booleani , non sono ambigui. I codici di ritorno del processo non sono valori booleani.
Andrew Spencer,

13
Perché l'intero paragrafo del link fornito è stato ignorato in questa risposta? "Il progetto più comunemente visto è quello di imitare i numerosi flag simili a booleani utilizzati dalle visualizzazioni del dizionario dei dati di Oracle, selezionando" Y "per true e" N "per false. Tuttavia, per interagire correttamente con ambienti host, come JDBC, OCCI, e altri ambienti di programmazione, è meglio selezionare 0 per false e 1 per true in modo che possa funzionare correttamente con le funzioni getBoolean e setBoolean. " Dichiarano che mentre 'Y / N' è comune, si consiglia di utilizzare '0/1' per aumentare la compatibilità con gli ambienti host.
justin.hughey,

28

Oracle stesso utilizza Y / N per i valori booleani. Per completezza va notato che pl / sql ha un tipo booleano, solo le tabelle non lo fanno.

Se si utilizza il campo per indicare se il record deve essere elaborato o meno, è possibile considerare l'utilizzo di Y e NULL come valori. Questo crea un indice molto piccolo (lettura veloce) che occupa pochissimo spazio.


7
+1 Aspetto positivo delle viste e delle tabelle interne di Oracle che utilizzano S / N. Se Oracle lo fa in questo modo, deve essere giusto! :)
Jeffrey Kemp il

Puoi spiegare come Y e NULL formano un piccolo indice rispetto a Y e N?
Styfle

6
I NULL non sono indicizzati in Oracle, quindi se il tuo indice contiene pochi caratteri Y, ma soprattutto i NULL avrai un indice molto piccolo.
Leigh Riffel,

25

Per utilizzare la minima quantità di spazio è necessario utilizzare un campo CHAR limitato a "Y" o "N". Oracle non supporta i tipi di dati BOOLEAN, BIT o TINYINT, quindi un byte di CHAR è il più piccolo possibile.


19

L'opzione migliore è 0 e 1 (come numeri - un'altra risposta suggerisce 0 e 1 come CHAR per l'efficienza dello spazio, ma questo è un po 'troppo contorto per me), usando NOT NULL e un vincolo di controllo per limitare il contenuto a quei valori. (Se hai bisogno che la colonna sia nullable, allora non hai a che fare con un booleano ma con un elenco con tre valori ...)

Vantaggi di 0/1:

  • Indipendente dalla lingua. 'Y' e 'N' andrebbero bene se tutti lo usassero. Ma loro no. In Francia usano "O" e "N" (l'ho visto con i miei occhi). Non ho programmato in Finlandia per vedere se usano 'E' e 'K' lì - senza dubbio sono più intelligenti di così, ma non puoi esserne sicuro.
  • Congruente con la pratica in linguaggi di programmazione ampiamente utilizzati (C, C ++, Perl, Javascript)
  • Gioca meglio con il livello applicazione, ad esempio Hibernate
  • Porta a SQL più concisi, ad esempio, per scoprire quante banane sono pronte per essere mangiate al select sum(is_ripe) from bananasposto di select count(*) from bananas where is_ripe = 'Y'o addirittura (yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Vantaggi di 'Y' / 'N':

  • Occupa meno spazio di 0/1
  • È ciò che Oracle suggerisce, quindi potrebbe essere ciò a cui alcune persone sono più abituate

Un altro poster ha suggerito "Y" / null per i miglioramenti delle prestazioni. Se hai dimostrato di aver bisogno delle prestazioni, quindi abbastanza onesto, ma altrimenti evita dal momento che rende le query meno naturali ( some_column is nullanziché some_column = 0) e con un join sinistro confonderai la falsità con record inesistenti.


3
In questi giorni scopri che molti booleani sono TriState, vale a dire vero, falso e sconosciuto. che si adatta perfettamente all'idea nulla del database. semplicemente perché molte volte sapere che non è stata data alcuna risposta è di vitale importanza
MikeT

1
Sì, può essere richiesto true-false-unknown, anche se se fossi esigente (cosa che sono), direi che non dovrebbe essere descritto come un booleano, perché non lo è.
Andrew Spencer,

2
se sarai così esigente, puoi fare lo stesso argomento per ogni tipo di dati. come sotto la definizione rigorosa integer, double (suppongo che dovrei dire una doppia lunghezza a complemento in virgola mobile), binario, stringa, ecc. tutti presuppongono che venga fornito un valore ma le implementazioni del database aggiungono sempre un'opzione di valore null Booleano non è diverso
MikeT

1
vero, una nota positiva per il tuo metodo se configuri correttamente il tuo numero, può anche essere memorizzato nello stesso byte singolo di un campo char, il che annulla l'argomento size contro l'utilizzo di 0/1, al momento non riesco a trovare il link ma la memoria per un numero varia da 1 a 22 byte a seconda della configurazione
MikeT

4
Sospetto che i downvotes siano dovuti a un punto di vista legacy sulla scelta dell'implementazione più efficiente in termini di memoria. Al giorno d'oggi l'efficienza della memoria è molto meno prioritaria e dovrebbe essere presa in considerazione dopo l'usabilità e la compatibilità. A chiunque possa rispondere a questo commento, consiglio di leggere sull'ottimizzazione prematura. Questo è esattamente ciò che accade scegliendo 'S / N' basato esclusivamente sull'efficienza della memoria. Stai perdendo la compatibilità nativa con una serie di framework comunemente usati a causa di quella decisione.
justin.hughey,

5

1/0 o Y / N con un vincolo di controllo su di esso. la via etere va bene. Personalmente preferisco 1/0 poiché lavoro molto in perl, e rende molto semplice eseguire operazioni booleane perl sui campi del database.

Se vuoi una discussione davvero approfondita di questa domanda con uno degli honchos di Oracoli, controlla cosa ha da dire Tom Kyte a riguardo qui


Si dice che 1/0 sia "meno efficiente in termini di memoria" ma ... mi piace anche di più (e il letargo a quanto pare richiede 1/0 per un valore booleano)
rogerdpack

1/0 è l'impostazione predefinita di Hibernate per un valore booleano, ma puoi definire qualsiasi mapping personalizzato che ti piace.
Andrew Spencer,

@rogerdpack è perché un campo char è 1 byte o 2 byte per nchar, dove a seconda di come è definito un numero può essere
compreso tra

4

Il database su cui ho svolto gran parte del mio lavoro ha usato "Y" / "N" come booleani. Con tale implementazione, puoi eseguire alcuni trucchi come:

  1. Conta le righe vere:
    SELEZIONA SOMMA (CASO QUANDO BOOLEAN_FLAG = 'Y' POI 1 ALTRO 0) DA X

  2. Quando si raggruppano le righe, applicare la logica "Se una riga è vera, allora tutte sono vere":
    SELEZIONARE MAX (BOOLEAN_FLAG) DA Y
    Al contrario, utilizzare MIN per forzare il raggruppamento falso se una riga è falsa.


4
in effetti gli esempi mostrati sono utili anche per l'approccio 0/1 - e, IMHO, più veloce.
igorsantos07,

2

Un esempio funzionante per implementare la risposta accettata aggiungendo una colonna "Booleana" a una tabella esistente in un database Oracle (usando il 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))
);

In questo modo viene creata una nuova colonna my_table_namechiamata my_new_boolean_columncon valori predefiniti pari a 0. La colonna non accetta i NULLvalori e limita i valori accettati a uno 0o1 .


1

Nei nostri database utilizziamo un enum che ci assicura di passarlo VERO o FALSO. Se lo fai in uno dei primi due modi, è troppo facile iniziare ad aggiungere un nuovo significato all'intero senza passare attraverso un disegno appropriato, o finire con quel campo char con Y, y, N, n, T, t, Valori F, f e dover ricordare quale sezione del codice utilizza quale tabella e quale versione di true sta utilizzando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.