Perché Oracle 9i considera una stringa vuota come NULL?


216

So che non considera '' come NULL, ma che non fa molto per dirmi il motivo per cui questo è il caso. A quanto ho capito le specifiche SQL, "" non è lo stesso di NULL- uno è un dato valido e l'altro indica l'assenza di quelle stesse informazioni.

Sentiti libero di speculare, ma per favore indica se è così. Se c'è qualcuno di Oracle che può commentarlo, sarebbe fantastico!


9
Sentiti libero di speculare? In qualche modo non credo che ti fornirà la più grande serie di risposte ..
SCdF,

1
Suppongo di no, ma non ero sicuro che ci fosse alcuna certezza sull'argomento, quindi ho pensato di aprire le porte. Sembra aver funzionato bene, finora.
Chris R,


Risposte:


216

Credo che la risposta sia che Oracle sia molto, molto vecchia.

Ai vecchi tempi prima che esistesse uno standard SQL, Oracle prese la decisione di progettazione che erano stringhe vuote in VARCHAR/ VARCHAR2colonne NULLe che c'era solo un senso di NULL (ci sono teorici relazionali che avrebbero differenziato tra i dati che non sono mai stati richiesti, dati in cui la risposta esiste ma non è nota all'utente, dati in cui non esiste una risposta, ecc. che costituiscono tutti un senso di NULL).

Quando lo standard SQL arrivò e concordò sul fatto che NULLe la stringa vuota erano entità distinte, c'erano già utenti Oracle che avevano il codice che presumeva che i due fossero equivalenti. Quindi a Oracle è rimasta sostanzialmente la possibilità di rompere il codice esistente, violare lo standard SQL o introdurre una sorta di parametro di inizializzazione che cambierebbe la funzionalità di un numero potenzialmente elevato di query. La violazione dello standard SQL (IMHO) è stata la meno distruttiva di queste tre opzioni.

Oracle ha lasciato aperta la possibilità che il VARCHARtipo di dati cambierebbe in una versione futura per aderire allo standard SQL (motivo per cui tutti usano VARCHAR2in Oracle poiché il comportamento di quel tipo di dati è garantito per rimanere lo stesso in futuro).


60

Tom Kyte VP di Oracle:

Un varchar di lunghezza ZERO viene considerato NULL.

'' non è trattato come NULL.

'' quando assegnato a un carattere (1) diventa '' (i tipi di carattere sono stringhe vuote imbottite).

'' quando assegnato a varchar2 (1) diventa '' che è una stringa di lunghezza zero e una stringa di lunghezza zero è NULL in Oracle (non è lungo '')


17
Wow, Tom è piuttosto snarky. Dato che le domande riguardano una divergenza egregia da SQL92, penseresti che sarebbe meno incisivo a riguardo ... anche se potrebbe essere stanco di rispondere.
Chris R,

8
La cosa migliore di Tom è che ottieni una risposta chiara, che afferma esattamente cosa pensa. Cerca alcuni dei commenti in cui le persone hanno usato il testo parlato su Chiedi a Tom
Chris Gill il

9
Ma sarebbe più preciso se la seconda riga fosse cambiata in '' non sempre viene considerata NULL.
ypercubeᵀᴹ

2
@ypercube La citazione non diventa più precisa cambiando la parola effettivamente utilizzata da Tom. Se pensi che Tom l'abbia formulato in modo confuso, mmm. Può essere. Penso che sia perfetto . Le situazioni più confuse si presentano quando ''viene implicitamente convertito in un VARCHAR2, come quello cast('' as char(1)) is nullche è ... sorprendentemente VERO
sehe

1
@sehe il bit confuso per me è selezionare 1 dal doppio dove ('' è null)
matt freake

20

Sospetto che ciò abbia molto più senso se si pensa a Oracle come probabilmente avevano fatto gli sviluppatori precedenti, come un backend glorificato per un sistema di immissione dei dati. Ogni campo nel database corrispondeva a un campo in una forma che un operatore di immissione dei dati vedeva sul suo schermo. Se l'operatore non ha digitato nulla in un campo, che sia "data di nascita" o "indirizzo", i dati per quel campo sono "sconosciuti". Non c'è modo per un operatore di indicare che l'indirizzo di qualcuno è davvero una stringa vuota e che comunque non ha molto senso.


5
Ciò ha senso solo se si presume che ogni campo in un sistema di immissione dei dati sia obbligatorio. Una non risposta a un campo non obbligatorio (ad es. "Nome del cane") è valida, quindi una stringa vuota ha ancora uno scopo distinto da NULL. Anche con tale presupposto, dubito che i primi sviluppatori pensassero a Oracle come un "backend glorificato per un sistema di inserimento dati", quindi non sono sicuro che questa risposta abbia senso.
Jared,

19

La documentazione Oracle avvisa gli sviluppatori di questo problema, risalendo almeno alla versione 7.

Oracle ha scelto di rappresentare NULL con la tecnica del "valore impossibile". Ad esempio, un NULL in una posizione numerica verrà memorizzato come "meno zero", un valore impossibile. Tutti gli zero negativi risultanti dai calcoli verranno convertiti in zero positivo prima di essere memorizzati.

Oracle ha anche scelto, erroneamente, di considerare la stringa VARCHAR di lunghezza zero (la stringa vuota) come un valore impossibile e una scelta adatta per rappresentare NULL. Si scopre che la stringa vuota è lungi dall'essere un valore impossibile. È persino l'identità sotto l'operazione di concatenazione di stringhe!

La documentazione Oracle avverte i progettisti e gli sviluppatori di database che alcune versioni future di Oracle potrebbero interrompere questa associazione tra la stringa vuota e NULL e interrompere qualsiasi codice che dipende da tale associazione.

Esistono tecniche per contrassegnare i NULL diversi dai valori impossibili, ma Oracle non li ha utilizzati.

(Sto usando la parola "posizione" sopra per indicare l'intersezione di una riga e una colonna.)


La documentazione di Oracle avverte i progettisti e gli sviluppatori di database che alcune versioni future di Oracle potrebbero interrompere questa associazione tra la stringa vuota e NULL e interrompere qualsiasi codice che dipende da tale associazione. Potresti fornire riferimento a questa affermazione?
Piotr Dobrogost,


2

La stringa vuota è uguale a NULL semplicemente perché è il "male minore" rispetto alla situazione in cui i due (stringa vuota e null) non sono uguali.

Nelle lingue in cui NULL e String vuota non sono uguali, è necessario verificare sempre entrambe le condizioni.


Basta impostare il not nullvincolo sulla colonna e controllare solo la stringa vuota.
Egor Skriptunoff,

6
Controllare entrambe le condizioni è banale: WHERE Field <> ''restituisce vero solo se il campo non è NULL e non è vuoto, su database con comportamento ANSI per stringhe vuote.

1

Secondo i documenti ufficiali 11g

Oracle Database attualmente considera un valore di carattere con una lunghezza pari a zero come null. Tuttavia, ciò potrebbe non essere vero nelle versioni future e Oracle consiglia di non trattare le stringhe vuote come null.

Possibili ragioni

  1. val IS NOT NULL è più leggibile di val != ''
  2. Non è necessario controllare entrambe le condizioni val != '' and val IS NOT NULL

5
In un database completamente conforme ANSI, non è necessario verificare entrambe le condizioni. val <> ''esclude già NULL. Forse intendevi val = '' OR val IS NULL. Ma sono utili stringhe vuote che non si confrontano come NULL !
ErikE,

Sono d'accordo con la parte di confronto.
Sorter il

0

Esempio dal libro

   set serveroutput on;   
    DECLARE
    empty_varchar2 VARCHAR2(10) := '';
    empty_char CHAR(10) := '';
    BEGIN
    IF empty_varchar2 IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
    END IF;


    IF '' IS NULL THEN
    DBMS_OUTPUT.PUT_LINE(''''' is NULL');
    END IF;

    IF empty_char IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
    ELSIF empty_char IS NOT NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
    END IF;

    END;

-1

Perché non trattarlo come NULL non è particolarmente utile.

Se si commette un errore in quest'area su Oracle, di solito si nota subito. In SQL Server, tuttavia, sembrerà funzionare e il problema si presenta solo quando qualcuno inserisce una stringa vuota anziché NULL (forse da una libreria client .net, dove null è diverso da "", ma di solito le tratti allo stesso modo ).

Non sto dicendo che Oracle abbia ragione, ma mi sembra che entrambe le strade siano approssimativamente ugualmente cattive.


2
Molto, molto più facile da eseguire il debug. Inoltre, se vedi una cella vuota o input sullo schermo, sai che i dati nel DB sono nulli. In altri DB in cui '' <> NULL, non è possibile "vedere" se i dati sono nulli o '', questo porta a bug molto subdoli. '' = null è l'opzione più sana, anche se non è standard.
Lucio M. Tato,

2
"In altri DB in cui '' <> NULL, non è possibile" vedere "se i dati sono null o ''” => Normalmente, gli strumenti DB visualizzano i NULL in modo diverso dalle stringhe vuote. In realtà, anche Oracle SQL Developer mostra i NULL come "(null)". Immagino che questo sia per distinguere NULL da spazi bianchi, ma non è correlato alla differenza tra NULL e stringhe vuote.
Didier L,

-6

In effetti, non ho avuto nient'altro che difficoltà a gestire Oracle, compresi valori di data / ora non validi (non possono essere stampati, convertiti o altro, ho appena guardato con la funzione DUMP ()) che possono essere inseriti nel database, apparentemente attraverso un bug versione del client come colonna binaria! Questo per quanto riguarda la protezione dell'integrità del database!

Gestione Oracle dei collegamenti NULL:

http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/

http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html


1
valori di dati non validi? Non sono sicuro di cosa significhi. Hai pubblicato questo come una domanda qui?

1
Il problema ha preceduto lo stackoverflow - non ho ricevuto informazioni utili dai forum Oracle e ho creato una soluzione alternativa - rintraccerò le mie note e le pubblicherò qui.
Cade Roux,

Dettagli pubblicati come domanda qui.
Cade Roux,

-6

Prima di tutto, le stringhe null e null non erano sempre trattate come le stesse da Oracle. Una stringa nulla è, per definizione, una stringa che non contiene caratteri. Questo non è affatto uguale a null. NULL è, per definizione, l'assenza di dati.

Cinque o sei anni circa, la stringa null è stata trattata diversamente da null da Oracle. Mentre, come null, la stringa null era uguale a tutto e diversa da tutto (che penso vada bene per null, ma totalmente SBAGLIATA per stringa null), almeno la lunghezza (stringa null) restituirebbe 0, come dovrebbe poiché la stringa null è una stringa di lunghezza zero.

Attualmente in Oracle, length (null) restituisce null che immagino sia OK, ma length (null string) restituisce anche null che è totalmente SBAGLIATO.

Non capisco perché abbiano deciso di iniziare a trattare questi 2 "valori" distinti allo stesso modo. Significano cose diverse e il programmatore dovrebbe avere la capacità di agire su ciascuno in modi diversi. Il fatto che abbiano cambiato la loro metodologia mi dice che in realtà non hanno idea di come questi valori debbano essere trattati.


Citazione richiesta per fare una distinzione tra "stringa nulla" e valore NULL. In qualsiasi database tranne Oracle, un VARCHARcampo può avere un valore (zero o più caratteri) o nessun valore (NULL), punto e punto.

"Cinque o sei anni fa" dal 2011 rientrerebbe nei tempi 10g (10.1 rilasciato nel 2003, 10.2 nel 2005). 10g non ha assolutamente introdotto cambiamenti globali nella gestione dei valori null e non vi è mai stata alcuna distinzione tra NULLuna stringa a valore zero e tale distinzione non ha senso. Temo che questa risposta sia una fantasia completa.
William Robertson,
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.