2010-03-11 9 views
23

Io lavoro come sviluppatore su un piccolo team di sviluppo, e qualcosa mi ha infastidito al punto in cui ho deciso di agire ...mancanza di Oracle di un tipo di dati di bit per le colonne della tabella

Oracle non supporta un po ' tipo di dati - o qualsiasi altra cosa che abbia senso in scenari veri/falsi. Imperterrito tuttavia, prima di entrare nel team, i miei antenati hanno deciso di utilizzare invece i campi char (1), usando una lettera specifica per denotare sì/true. Sfortunatamente, la nostra applicazione è utilizzata da persone di tutto il mondo e, per ragioni che sfidano apertamente tutti i miei tentativi di comprensione, il valore utilizzato varia attraverso la localizzazione.

Sì, lo so che è del tutto inutile per i valori nel back-end che l'utente non vede mai - però ...

ho notato che questa pratica sembra essere sempre portato avanti nel nuovo sviluppo, che mi sembra pazzesco - quindi sto pensando di proporre Number (1,0) per questo invece - 0 è considerato falso/no, qualsiasi altra cosa viene interpretata come vero/sì ...

Domanda semplice - qualcuno può pensare di una ragione potrebbe essere una cattiva idea?

Mentre ci siamo, qualcuno sa perché Oracle non supporta un tipo booleano semplice? Non è un'ammissione GLARING?

Cheers in anticipo,

Martin.

+0

Sotto tutta la riserva, Oracle non offre un tipo di dati BOOL o BOOLEAN (forse è solo con le ultime versioni ...)? Non riesco davvero a ricordare chiaramente. Non ho fatto Oracle per più di due anni. Comunque, NUMBER (1) va bene, dice quello che serve, proprio come un BIT - 0 o 1, un numero (1) - 0 o 1, qual è la differenza? –

+4

@Will: il numero (1, 0) può essere qualsiasi numero di singola cifra (0-9), non solo 0 o 1. – Cameron

+0

Sì, certo! Ma non hai alcun controllo sui valori delle colonne datatable? –

risposta

10

Preferisco char (1) sul numero (1), poiché con una scelta ragionevole di caratteri, è ovvio quale carattere ha quale significato booleano.

Ovviamente dovresti combattere tutte le diverse varianti, scegline una e assicurane l'utilizzo mettendo i vincoli di controllo sulle colonne.

Anche se probabilmente è troppo tardi nel tuo caso, la generazione dello schema da un altro strumento spesso si occupa almeno del problema di coerenza. Personalmente preferisco l'ibernazione per questo scopo, ma questa è una situazione molto specifica.

E naturalmente questo è un lampo di obiezione. Per peggiorare, PL/SQL ha un valore booleano, ma non è possibile utilizzarlo nelle istruzioni SQL.

+0

Entrambe le risposte di Thilo sono buone - ma l'ho accettata a causa del consiglio di applicare la conformità attraverso i vincoli di controllo ... Sembra che la vera risposta sia "Tutti fanno la loro cosa, non c'è uno standard ... " –

+0

Puoi anche nominare la colonna di conseguenza come UPDATE_ALLOWED_YN –

2

Il numero (1) non è migliore di char (1). Soprattutto se sarà in aggiunta al carattere esistente (1). Ciò aggiungerà solo confusione.

FWIW, Oracle nelle viste interne (come USER_TAB_COLUMNS) utilizza varchar2 (3) (YES e NO). Non sono sicuro se siano al 100% coerenti qui, però.

+0

La mia ragione per pensare al numero (1,0) era che se non altro un valore avrebbe un significato definito definito. Prendo la tua opinione su tutto ciò che facciamo dovendo coesistere con il codice del passato, ma è inevitabile - e non così indesiderabile come semplicemente lasciare la situazione com'è attualmente ... Speravo anche che il la natura numerica sarebbe più semplice da elaborare per il server e, quindi, forse (in modo trascurabile) più veloce. Ti piacerebbe offrire un tipo di dati candidato? Il numero –

+1

(1) potrebbe essere un po 'più piccolo sullo spazio del disco, ma ad eccezione di tabelle enormi costituite quasi esclusivamente da "booleani", questo dovrebbe essere trascurabile. Inoltre hai sempre le opzioni di indici di compressione e bitmap che potrebbero risolvere alcuni degli effetti negativi relativi allo spazio. –

+2

@Jens: In realtà, il numero (1) è più grande. Vedi la mia risposta. – DCookie

13

Non sono nativo inglese, quindi tendo ad usare 1 e 0 o "1" e "0". Usare 'Y' e 'N' ha poco senso se non si sta codificando in inglese (sì, la codifica in linguaggio nativo esiste). Usare 'SI' e 'NO' o 'S' e 'N' non sembrano professionali (proprio come le variabili di denominazione con lettere accentate). Gli uni e gli zeri, al contrario, sono piuttosto standard se hai codificato in C, PHP o JavaScript. In ogni caso, aggiungo sempre il vincolo appropriato per disabilitare qualsiasi altro carattere. A parte i problemi soggettivi, non penso che ci siano notevoli miglioramenti nelle prestazioni nella scelta di CHAR o NUMBER. Mi piacciono un po 'di più perché non ho bisogno di citarli :)

Sono d'accordo che è un'omissione abbagliante ma ho letto discussioni accese sul tema in alcuni forum Oracle; è una specie di problema religioso. Alcuni sostengono che i booleani appartengono ai tipi di dati dell'applicazione e non hanno posto nel nucleo del database.Onestamente, credo che sia uno di quelli che siamo stati così a lungo senza che sarebbe stato meglio dire che era così.

A proposito, MySQL ha un tipo BOOLEAN ma è un sinonimo di TINYINT (1) quindi alla fine equivale a 1 e 0; che va bene, perché ha anche le costanti VERO e FALSO che valutano a 1 e 0.

+0

Sono tentato di essere d'accordo con te - e sì, ho fatto qualche C/PHP nel mio passato. Preferisco decisamente i numeri, ma sono sorpreso di scoprire che occupano più spazio (vedi sopra) –

+5

+1 per "We-Have-Been-So-Long-Senza-It-That-Had-Better-Say-It -Su-On-Purpose "Dovremmo coniare quella frase: WHBSLWITWHBSIWOP. – Baodad

8

Ecco una discussione Ask Tom sull'argomento. Fornisce una visione incentrata su Oracle sul problema.

quanto riguarda lo storage, char (1) è in realtà un po '(no pun intended) più efficiente:

SQL> CREATE TABLE xx (c CHAR(1), n NUMBER); 

Table created 

SQL> insert into xx values('T', 1); 

1 row inserted 

SQL> select dump(c), dump(n) from xx; 

DUMP(C)    DUMP(N) 
------------------- ------------- 
Typ=96 Len=1: 84 Typ=2 Len=2: 193,2 
+3

Questo è molto interessante - e non quello che mi aspettavo. Personalmente sento ancora che i numeri hanno più chiarezza ... Ho letto la discussione su Ask Tom prima di vedere il tuo post (su Google), ma non sono d'accordo con la sua giustificazione di non avere un booleano/bit ... –

+1

@ Martin: Vedi questa discussione SO per ulteriori chiarimenti, prestando particolare attenzione alla risposta di Quassnoi: http://stackoverflow.com/questions/1087210/oracle-number-comparisons/1087873#1087873 – DCookie

+4

@ Martin: Sono d'accordo, non c'è alcun motivo logico per escludere il tipo BOOLEAN nel database, solo quelli pragmatici. Oracle è un po 'schizofrenico sul problema, dal momento che ha un tipo BOOLEAN nel linguaggio PL/SQL. Solo questo è la fonte di una grande confusione per i programmatori Oracle la prima volta che li incontrano. – DCookie

23

Utilizzare un CHAR (1), e un vincolo per consentire solo '1' e '0 '.

...

col CHAR(1), 
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0')) 
+0

Ora questa risposta mi piace molto .. –

+0

Questo è quello che stavo per scrivere dopo aver fatto ulteriori ricerche sul caso. Ad ogni modo, ecco un link che dovrebbe aiutare. http://thinkoracle.blogspot.com/2005/07/oracle-boolean.html Inoltre, puoi definire te stesso un tipo di utente che sarebbe BIT, ad esempio, quindi accettando solo quei valori vincolati. Un altro link utile: http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i45441 –

+0

Non dimenticare "Default 0 Not Null", se necessario. Ho provato la necessità - per evitare l'inserimento nullo –

0

La domanda è vecchia, ma fino a quando si utilizza l'ultima versione di Oracle è ancora una domanda valida.

Vorrei risolvere il problema in questo modo: Creare una tabella che contenga i valori possibili per vero/falso più testo di visualizzazione localizzato per esempio. T $ KEYWORDS ITEMNO ITEMTEXT ITEMTEXT_DE ITEMTEXT_FE ... 0 Falso Falsch 1 True Wahr

Invece di Vero/Falso questo potrebbe essere anche selezionato, non selezionata, ecc

E poi aggiungere una chiave foreigh alla tua colonna per questo tavolo. In questo modo hai solo valori validi e non cambiano con la localizzazione.

Un'altra buona soluzione imho utilizza un vincolo di controllo sulla colonna di dati. Questo ofc non funziona se i tuoi valori potrebbero essere diversi nello stesso database/colonna a seconda della localizzazione dei client.

alter table tblLocations add flag number CONSTRAINT <constraintname> CHECK (flag IN (1,0));

-1

https://docs.oracle.com/cd/E17952_01/refman-5.5-en/char.html enter image description here

Come detto DCookie, char (1) è più efficiente. Poiché VARCHAR2 (VARCHAR) vuoto contiene 1 byte, ma quando memorizziamo 1 carattere, vuoto 1 byte size + con carattere 1 byte size -> 2 byte necessario memorizzare 1 carattere in varchar

0

Oracle internamente utilizza "bit" (non un tipo di dati di per sé) in diverse viste del dizionario dati.

Ad esempio, dba_users vista ha:

.. 
     , DECODE (BITAND (u.spare1, 128), 128, 'YES', 'NO') 
.. 
     , DECODE (BITAND (u.spare1, 256), 256, 'Y', 'N') 
.. 

che mostra un modo per risolvere questo in modo. Se non è necessario modificare spesso i bit "booleani", è possibile utilizzare lo stesso approccio che Oracle ha avuto da Oracle 6 (almeno). Crea una tabella con una colonna NUMBER e una VISUALIZZA sopra a quella che nasconde la complessità delle operazioni BITAND.

ps.Una nota a margine, Oracle JDBC ha un tipo di dati "Bit" https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT così come già sapete che PL/SQL ha Booleano. Anche se probabilmente non ti aiuta molto. Vedi l'approccio BITAND sopra se è adatto al tuo caso.

Problemi correlati