MySQL, è meglio inserire una stringa NULL o vuota?


230

Ho un modulo su un sito Web che ha molti campi diversi. Alcuni dei campi sono opzionali mentre altri sono obbligatori. Nel mio DB ho una tabella che contiene tutti questi valori, è meglio inserire un valore NULL o una stringa vuota nelle colonne del DB in cui l'utente non ha inserito alcun dato?

Risposte:


220

Usando NULLè possibile distinguere tra "non inserire dati" e "mettere dati vuoti".

Alcune altre differenze:

  • A LENGTHdi NULLè NULL, a LENGTHdi una stringa vuota è 0.

  • NULLs sono ordinati prima delle stringhe vuote.

  • COUNT(message)conterà stringhe vuote ma non NULLs

  • Puoi cercare una stringa vuota usando una variabile associata ma non una NULL. Questa query:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    non corrisponderà mai a NULLin mytext, qualunque valore passi dal client. Per abbinare NULLs, dovrai usare un'altra query:

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
ma quale pensi sia più veloce? 0 o NULL o ""
Atul Dravid,

8
in InnoDB i NULL occupano meno spazio
Timo Huovinen il

37
Penso che questa sia una risposta accettabile, ma ignora anche totalmente l'elemento "best practice" della domanda e si concentra solo su fatti tangenzialmente rilevanti (ordinamento e lunghezza NULL? Questi non contano). Sulla maggior parte dei tipi di input di dati di testo non c'è differenza tra "nessuna risposta" e "risposta vuota", quindi penso che questa sia un'ottima domanda che merita una risposta migliore.
Nick,

6
I NULL funzionano egregiamente anche quando è impostato il campo UNICO. Ad esempio se hai un campo come la patente di guida per aggiungere il numero DL della persona e il ragazzo non ce l'ha. Poiché si tratta di un campo univoco, verrà aggiunta la prima persona senza il numero DL, ma non quella successiva poiché genererà un errore di vincolo univoco. Quindi, NULL è migliore.
Saifur Rahman Mohsin,

1
@Quassnoi ah scusa ... volevo dire, perché è una cattiva pratica impostare la patente di guida come unica ...?
Cedbeu,

44

Una cosa da considerare, se hai mai intenzione di cambiare database, è che Oracle non supporta le stringhe vuote . Vengono convertiti automaticamente in NULL e non è possibile eseguire query per loro utilizzando clausole come WHERE somefield = ''.


11
Mi è sembrato incredibilmente sospetto, anche sul tuo link, quindi l'ho provato. Campo nullo, impostato su '', l'oracolo lo ignora. La lunghezza dei rapporti è null anziché 0. È così sbagliato. Deve esserci un modo per aggirare questo. Penso che lo posterò come un'altra domanda.
Steve B.

1
Steve B.: Vedi questa domanda: stackoverflow.com/questions/1171196/...
Quassnoi

Grazie per il riferimento, anche se ancora non capisco il ragionamento. Inserito come stackoverflow.com/questions/1268177/…
Steve B.

Potrebbe valere la pena aggiornare la risposta per includere informazioni dal link pubblicato da Quassnoi
SamuelKDavis

7
Peoplesoft (con Oracle DB) utilizza un singolo spazio per indicare un valore vuoto. Incredibilmente stupido. Usano anche 0.00025 per indicare 0 per ETP poiché 0 non è consentito. Sono state fatte delle scelte adorabili in quel prodotto.
JP Duffy,

9

Una cosa da tenere a mente è che NULL potrebbe rendere i tuoi codepati molto più difficili. In Python ad esempio la maggior parte degli adattatori di database / ORM mappa NULLa None.

Quindi cose come:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

potrebbe comportare "Ciao, nessuno Joe Doe!" Per evitarlo hai bisogno di qualcosa come questo codice:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

Il che può rendere le cose molto più complesse.


25
A mio avviso, abusare del database per "correggere" errori nel codice o nel framework è una (molto) cattiva pratica di codifica. Quando non ci sono dati, devi semplicemente inserire NULL ed essere coerente nell'usarlo. Altrimenti devi usare istruzioni come: if (myString == null || myString = ""). Quando un oggetto non è impostato o definito nel codice, si utilizza anche NULL anziché una sorta di "segnaposto" (che secondo me è una stringa vuota).
Gertjan,

5
Dipende molto dalla tua lingua preferita. In Python "if not myString:" testa per None e "". Probabilmente principalmente una questione culturale. La "cattiva pratica" di Java Guys è l'eleganza della persona dinamica.
massimo

9

Meglio inserire NULLper coerenza nel database in MySQL. Le chiavi esterne possono essere memorizzate come NULLma NON come stringhe vuote.

Avrai problemi con una stringa vuota nei vincoli. Potrebbe essere necessario inserire un record falso con una stringa vuota univoca per soddisfare un vincolo di chiave esterna. Cattiva pratica immagino.

Vedi anche: una chiave esterna può essere NULL e / o duplicata?


Il problema dei vincoli mi ha fatto scattare in passato ed è per questo che "+1" questa risposta.
HPWD,

Ma se usi NULL assicurati di non finire mai con stringhe vuote. Facile da fare con molte tecnologie di interfaccia utente.
Montabile il

5

Non so quale sia la migliore pratica qui, ma generalmente vorrei sbagliare a favore del null a meno che tu non voglia che null significhi qualcosa di diverso da stringa vuota e l'input dell'utente corrisponda alla definizione di stringa vuota.

Nota che sto dicendo che devi definire come vuoi che siano diversi. A volte ha senso averli diversi, a volte no. Altrimenti, basta sceglierne uno e attenersi ad esso. Come ho detto, tendo a favorire il NULL per la maggior parte del tempo.

Oh, e tieni presente che se la colonna è nulla, è meno probabile che il record appaia praticamente in qualsiasi query che seleziona (ha una clausola where, in termini SQL) basata su quella colonna, a meno che la selezione non sia per una colonna nulla ovviamente.


1
... E ora che vedo la risposta sopra di me, penso che sia sicuro dire che la solita differenziazione che ti interesserebbe non è dati contro dati vuoti. :-)
Platinum Azure,

1

Se si utilizzano più colonne in un indice univoco e almeno una di queste colonne è obbligatoria (ovvero un campo modulo obbligatorio), se si impostano le altre colonne nell'indice su NULL, è possibile che si verifichino righe duplicate. Questo perché i valori NULL vengono ignorati in colonne univoche. In questo caso, utilizzare stringhe vuote nelle altre colonne dell'indice univoco per evitare righe duplicate.

COLONNE IN UN INDICE UNICO:
(event_type_id, event_title, data, posizione, url)

ESEMPIO 1:
(1, "BBQ", "2018-07-27", null, null)
(1, 'BBQ', '2018-07-27', null, null) // consentito e duplicato.

ESEMPIO 2:
(1, 'BBQ', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // NON consentito poiché duplicato.

Ecco alcuni codici:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Ora inserisci questo per vedere che consentirà le righe duplicate:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

Ora inseriscilo e verifica che non sia consentito:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

Quindi, non c'è giusto o sbagliato qui. Sta a te decidere cosa funziona meglio con le tue regole aziendali.

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.