it-swarm.it

SQL: stringa vuota vs valore NULL

So che questo argomento è un po 'controverso e ci sono molti articoli/opinioni fluttuanti su Internet. Sfortunatamente, la maggior parte di loro presume che la persona non sappia quale sia la differenza tra NULL e stringa vuota. Quindi raccontano storie di risultati sorprendenti con join/aggregati e generalmente tengono lezioni SQL un po 'più avanzate. In questo modo, mancano assolutamente il punto e sono quindi inutili per me. Quindi spero che questa domanda e tutte le risposte si sposteranno un po 'in avanti.

Supponiamo di avere una tabella con informazioni personali (nome, nascita, ecc.) In cui una delle colonne è un indirizzo e-mail con tipo varchar. Partiamo dal presupposto che per qualche motivo alcune persone potrebbero non voler fornire un indirizzo e-mail. Quando si inseriscono tali dati (senza e-mail) nella tabella, sono disponibili due opzioni: impostare la cella su NULL o impostarla su stringa vuota (''). Supponiamo di essere a conoscenza di tutte le implicazioni tecniche della scelta di una soluzione rispetto a un'altra e di poter creare query SQL corrette per entrambi gli scenari. Il problema è anche quando entrambi i valori differiscono a livello tecnico, sono esattamente gli stessi a livello logico. Dopo aver visto NULL e '' Sono giunto a una conclusione: non conosco l'indirizzo e-mail del ragazzo. Inoltre, non importa quanto ci abbia provato, non sono stato in grado di inviare un'e-mail utilizzando NULL o stringa vuota, quindi apparentemente la maggior parte dei server SMTP là fuori concordano con la mia logica. Quindi tendo a usare NULL dove non conosco il valore e considero una stringa vuota una cosa negativa.

Dopo alcune intense discussioni con i colleghi sono arrivata con due domande:

  1. ho ragione nel dare per scontato che l'uso di una stringa vuota per un valore sconosciuto stia facendo "mentire" un database sui fatti? Per essere più precisi: usando l'idea di SQL di ciò che è valore e cosa non lo è, potrei giungere alla conclusione: abbiamo un indirizzo e-mail, solo scoprendo che non è nullo. Ma più tardi, quando provo a inviare e-mail, giungerò a una conclusione contraddittoria: no, non abbiamo un indirizzo e-mail, che il database @! # $ Deve aver mentito!

  2. Esiste uno scenario logico in cui una stringa vuota '' potrebbe essere un buon vettore di informazioni importanti (oltre al valore e nessun valore), che sarebbe problematico/inefficiente da memorizzare in qualsiasi altro modo (come colonna aggiuntiva). Ho visto molti post che affermano che a volte è bene usare una stringa vuota insieme a valori reali e NULL, ma finora non ho visto uno scenario logico (in termini di progettazione SQL/DB).

Post scriptum Alcune persone saranno tentate di rispondere, che è solo una questione di gusti personali. Non sono d'accordo Per me è una decisione di progettazione con conseguenze importanti. Quindi mi piacerebbe vedere le risposte in cui il parere su questo è supportato da alcuni motivi logici e/o tecnici.

73
Jacek Prucia

Direi che NULL è la scelta corretta per "nessun indirizzo email". Esistono molti indirizzi di posta elettronica "non validi" e "" (stringa vuota) è solo uno. Ad esempio "pippo" non è un indirizzo e-mail valido, "a @ b @ c" non è valido e così via. Quindi, solo perché "" non è un indirizzo email valido non è un motivo per usarlo come valore "nessun indirizzo email".

Penso che tu abbia ragione nel dire che "" non è il modo corretto di dire "Non ho un valore per questa colonna". "" è un valore.

Un esempio di dove "" potrebbe essere un valore valido, separato da NULL potrebbe essere il secondo nome di una persona. Non tutti hanno un secondo nome, quindi è necessario distinguere tra "nessun secondo nome" ("" - stringa vuota) e "Non so se questa persona ha un secondo nome o meno" (NULL ). Probabilmente ci sono molti altri esempi in cui una stringa vuota è ancora un valore valido per una colonna.

84
Dean Harding

Pur concordando con i commenti di cui sopra, aggiungerei questo argomento come motivazione principale:

  1. È ovvio per qualsiasi programmatore che guarda un database che un campo contrassegnato come NULL è un campo opzionale. (ovvero il record non richiede dati per quella colonna)
  2. Se si contrassegna un campo NON NULL, qualsiasi programmatore dovrebbe assumere intuitivamente che si tratta di un campo obbligatorio.
  3. In un campo che consente null, i programmatori dovrebbero aspettarsi di vedere null anziché stringhe vuote.

Per motivi di codifica intuitiva auto-documentante, utilizzare NULL invece di stringhe vuote.

41
colinbashbash

Nel tuo esempio se è un valore direttamente dal campo web, userei una stringa vuota. Se l'utente ha la possibilità di specificare che non desidera fornire e-mail o può eliminarlo, quindi NULL.

Ecco il link con i punti che potresti prendere in considerazione: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945

--- modificato (in risposta al commento di Thomas) ---

I database non vivono senza le applicazioni che li usano. La definizione di NULL o '' non ha alcun valore, se l'applicazione non può utilizzarlo correttamente.

Considera un esempio in cui l'utente sta compilando il modulo LONG e premi invio, che invierà la richiesta persistente al server. Potrebbe essere nel mezzo di inserire la sua email. Molto probabilmente vuoi archiviare tutto ciò che ha nel campo e-mail, quindi in seguito potrebbe finirlo. E se avesse inserito solo un personaggio? Cosa succede se immette un carattere e poi lo elimina? Quando l'e-mail non è richiesta, a volte gli utenti vogliono eliminarla: il modo più semplice per cancellare il campo. Anche nel caso in cui l'e-mail non sia richiesta vale la pena convalidarla prima dell'invio.

Un altro esempio: l'utente fornisce l'e-mail come spamto @ [bigcompany] .com - in tal caso non è necessario inviare e-mail, anche se è presente e valida (e può anche esistere). L'invio di uno di questi potrebbe essere economico, ma se ci sono 10K utenti con tali e-mail per abbonamenti giornalieri, tale convalida potrebbe risparmiare molto tempo.

6

Usa null.

Non ha senso memorizzare un valore di '', quando semplicemente renderà nulla il campo nella tabella. Rende anche le domande più ovvie.

Quale query SQL è più ovvia e leggibile se si desidera trovare utenti con un indirizzo e-mail?

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

Direi 2 lo è. Sebbene 3 sia più robusto nei casi in cui sono archiviati dati errati.

Nel caso dell'indirizzo e-mail sul modulo, che è facoltativo, dovrebbe essere riportato anche nella tabella. In SQL, è un campo nullable, il che significa che non è noto.

Non riesco a pensare a un valore aziendale ragionevole nel memorizzare una stringa vuota in una tabella diversa dal semplice design errato. È come memorizzare un valore stringa di 'NULL' o 'BLANK' e avere sviluppatori assume che è null o una stringa vuota. Per me è un cattivo design. Perché conservarlo quando c'è NULL ??

Usa NULL e renderai tutti un po 'più felici.

ALTRE INFORMAZIONI:

SQL utilizza un sistema logico a tre valori: True, False e Unknown.

Per una spiegazione migliore e più dettagliata, raccomando agli sviluppatori di leggere: Query SQL - oltre TRUE e FALSE .

5
spong

Sfortunatamente, Oracle ha confuso la rappresentazione della stringa VARCHAR di lunghezza zero con la rappresentazione di NULL. Entrambi sono rappresentati internamente da un singolo byte con valore zero. Questo rende la discussione ancora più difficile.

Molta della confusione che circonda NULL ruota attorno a logica a tre valori. Considera il seguente pseudocodice:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

Non ti aspetteresti il ​​terzo messaggio, ma è quello che otterrai, in base a tre logiche apprezzate. Tre logiche apprezzate conducono le persone verso numerosi bug.

Un'altra fonte di confusione è trarre inferenze dall'assenza di dati, come trarre un'inferenza dal cane che non abbaiava nella notte. Spesso queste inferenze non erano ciò che lo scrittore del NULL intendeva cnvey.

Detto questo, ci sono molte situazioni in cui NULL gestisce bene l'assenza di dati e produce esattamente i risultati desiderati. Un esempio sono le chiavi esterne nelle relazioni opzionali. Se si utilizza un valore NULL per indicare nessuna relazione in una determinata riga, quella riga verrà eliminata da un join interno, proprio come ci si aspetterebbe.

Inoltre, tieni presente che anche se eviti NULL completamente nei dati memorizzati (sesto modulo normale), se esegui un join esterno, dovrai comunque far fronte a NULL.

5
Walter Mitty

Penso che la risposta di Dean Hardings lo copra davvero bene. Detto questo, vorrei ricordare che quando si parla di NULL rispetto a stringhe vuote a livello di DB, è necessario riflettere sugli altri tipi di dati. Conserveresti la data minima quando non viene fornita la data? o -1 quando non viene fornito nessun int? Memorizzare un valore quando non si ha alcun valore significa che è necessario tenere traccia di un intero intervallo di non valori. Almeno uno per ogni tipo di dati (forse di più man mano che si ottengono casi in cui -1 è un valore effettivo, quindi è necessario disporre di un'alternativa, ecc.). Se hai bisogno/vuoi fare qualcosa di "confuso" a livello di applicazione che è una cosa, ma non è necessario inquinare i tuoi dati.

5
bendemes

per la specifica domanda tecnica, il problema non è nullo vs stringa vuota, è un errore di convalida. Una stringa vuota non è un indirizzo email valido!

per la domanda filosofica, la risposta è simile: convalida i tuoi input. Se una stringa vuota è un valore valido per il campo in questione, quindi aspettalo e codifica per esso; in caso contrario, utilizzare null.

Una stringa vuota sarebbe un valido input per rispondere alla domanda: cosa diceva il mimo alla giraffa?

3
Steven A. Lowe

Potrei pensare a un motivo per avere NULL e la stringa vuota:

  • Hai indirizzi email validi: [email protected]
  • Non ne hai nessuna (e probabilmente dovresti chiederne una): NULL
  • Sai che questa persona non ha un indirizzo email: Empty String.

Tuttavia, non lo consiglierei e utilizzerei un campo separato per chiedere se sai che non esiste.

2
Marcel

La domanda, a quanto ho capito, è quali interpretazioni di NULL e stringa vuota dovrebbero essere scelte. Questo dipende da quanti stati può essere presente il campo particolare.

L'interpretazione dipende da come si accede al database. Se nel codice è presente un livello che consente di estrarre completamente il database, è assolutamente accettabile la scelta di qualsiasi criterio (inclusi due simboli) che funzioni. (Documentare chiaramente la politica è importante, però). Tuttavia, se si accede al database in più punti, è necessario utilizzare uno schema molto semplice, poiché il codice sarà più difficile da mantenere e potrebbe essere errato in questo caso.

1
apoorv020

Beh, fondamentalmente a livello logico non c'è alcuna differenza tra valore "non valido" e "nessun input dell'utente", sono solo tutti "casi speciali" il più delle volte. Caso di errore.

Avere null richiede spazio aggiuntivo: ceil (colonne_con_null/8) in byte/per riga.

Cella vuota e null sono entrambi modi per contrassegnare qualcosa che non va/dovrebbe essere predefinito. Perché avresti bisogno di 2 stati "sbagliati"? Perché usare i NULL se occupano spazio aggiuntivo e significano esattamente le stesse delle stringhe vuote? Ciò introdurrà confusione e ridondanza quando si hanno due cose che significano (che potrebbero significare) esattamente lo stesso, è facile dimenticare che è necessario utilizzare NULL invece di stringhe vuote (se, ad esempio, l'utente ha preferito alcuni campi).

E i tuoi dati possono diventare un disastro. In un mondo perfetto diresti "i dati saranno sempre corretti e lo ricorderò" ... ma quando le persone devono lavorare in una squadra e non tutti sono esattamente al tuo livello non è raro vedere DOVE (aa. xx <> '' AND bb.zz IS NOT NULL)

Quindi, invece di correggere i membri del mio team a giorni alterni, impongo semplicemente una regola semplice. Nessun valore nullo, MAI!

Il conteggio dei valori NON-NULL è più veloce ... la semplice domanda è per cosa dovresti farlo?

1
Slawek

Tendo a vederlo non dal punto di vista del DB ma dal punto di vista del programma. So che questa domanda riguarda il clic SQL, ma in realtà quanti utenti accedono ai dati direttamente più a lungo?

In un programma non mi piace null/niente. Ci sono alcune eccezioni, ma sono proprio questo. E quelle eccezioni sono solo cattive implementazioni.

Quindi, se l'utente non ha inserito l'e-mail, dovrebbe esserci qualcosa che determina se questo è valido o meno. Se un messaggio di posta elettronica vuoto va bene, viene visualizzata una stringa vuota. Se l'utente non ha inserito un'e-mail e ciò viola una regola, l'oggetto dovrebbe indicarlo.

L'idea che nulla abbia significato è vecchia scuola ed è qualcosa che i programmatori moderni devono aggirare.

Anche nella progettazione di DB perché il campo e-mail non può consentire valori null e avere una stringa di lunghezza zero e un altro campo che indica se l'utente ha inserito qualcosa? È un po 'troppo chiedere a un DBMS? A mio avviso, il DB non dovrebbe gestire né la logica aziendale né la logica di visualizzazione. Non è stato costruito per questo e quindi fa un pessimo lavoro di gestione.

1
ElGringoGrande