Kiedy używać NULL, a kiedy używać pustego ciągu?

82

Interesuję się głównie MySQL i PostgreSQL, ale ogólnie możesz odpowiedzieć na następujące pytania:

  • Czy istnieje logiczny scenariusz, w którym przydatne byłoby odróżnienie pustego ciągu od NULL?
  • Jakie byłyby implikacje fizycznego przechowywania dla przechowywania pustego ciągu jako ...

    • ZERO?
    • Pusta struna?
    • Kolejne pole?
    • Jakikolwiek inny sposób?
Maniero
źródło

Odpowiedzi:

67

Powiedzmy, że rekord pochodzi z formularza służącego do gromadzenia informacji o nazwie i adresie. Wiersz 2 adresu będzie zwykle pusty, jeśli użytkownik nie mieszka w mieszkaniu. Pusty ciąg w tym przypadku jest całkowicie poprawny. Wolę używać NULL, aby oznaczać, że wartość jest nieznana lub nie została podana.

Nie sądzę, że w praktyce warto martwić się różnicą w fizycznym przechowywaniu. Jako administratorzy baz danych mamy znacznie większe ryby do smażenia!

Larry Coleman
źródło
2
+1 bardzo niewielu dba kiedykolwiek musiało martwić się różnicami prędkości / wielkości przy użyciu NULLlub nie
Patrick
28
Zgadzam się… Próbuję zarezerwować NULL na „nieznany”… pusty ciąg to „wiemy, że powinien być pusty”. Jest to szczególnie przydatne, gdy dane pochodzą z wielu źródeł
Joe
6
Zaległe - wartość NULL nie jest znana, określono pusty ciąg znaków.
ScottCher,
@ Larry jaki jest wpływ na wydajność? Jaka jest wydajność w przypadku tabel wielu kolumn w porównaniu z tabelami wielu wierszy?
Shimmy,
Zgadzam się, że jeśli istnieje rozróżnienie między brakiem podanej wartości a pustym ciągiem w zbiorze danych, powinieneś ich odpowiednio użyć, ale osobiście, jeśli nie potrzebuję tego rozróżnienia w moich danych, zawsze używam pustego ciągu, wyłącznie dlatego, że znajdź, że wynik zapytania z klienta MySQL w wierszu poleceń może być łatwiejszy do obejrzenia z pustymi ciągami zamiast z wieloma NULL -ami
RTF
25

Nie wiem o MySQL i PostgreSQL, ale pozwól mi potraktować to trochę ogólnie.

Jest jeden DBMS, a mianowicie Oracle, który nie pozwala wybrać użytkowników pomiędzy NULL a „”. To wyraźnie pokazuje, że nie jest konieczne rozróżnienie między nimi. Istnieją pewne irytujące konsekwencje:

Ustawiasz varchar2 na pusty ciąg taki jak ten:

Update mytable set varchar_col = '';

następujące prowadzi do tego samego wyniku

Update mytable set varchar_col = NULL;

Ale aby wybrać kolumny, w których wartość jest pusta lub NULL, musisz użyć

select * from mytable where varchar_col is NULL;

Za pomocą

select * from mytable where varchar_col = '';

jest poprawny pod względem składniowym, ale nigdy nie zwraca wiersza.

Z drugiej strony, podczas łączenia łańcuchów w Oracle. Warchary NULL są traktowane jako puste ciągi.

select NULL || 'abc' from DUAL;

daje abc . W innych przypadkach DBMS zwróciłoby wartość NULL.

Jeśli chcesz wyraźnie wyrazić, że wartość jest przypisana, musisz użyć czegoś takiego jak ''.

I musisz się martwić, czy przycinanie niepustych wyników daje NULL

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

To robi.

Teraz patrząc na DBMS, gdzie „” nie jest identyczne z NULL (np. SQL-Server)

Praca z „” jest na ogół łatwiejsza iw większości przypadków nie ma praktycznej potrzeby rozróżnienia między nimi. Jednym z wyjątków, jaki znam, jest sytuacja, gdy kolumna reprezentuje jakieś ustawienie i nie ma dla nich pustych ustawień domyślnych. Kiedy możesz rozróżnić „” i „NULL”, możesz wyrazić, że twoje ustawienie jest puste i uniknąć domyślnego ustawienia.

bernd_k
źródło
17

To zależy od domeny, nad którą pracujesz. NULLoznacza brak wartości (tzn. nie ma wartości ), a pusty ciąg oznacza, że ​​istnieje ciąg o zerowej długości.

Załóżmy na przykład, że masz tabelę do przechowywania danych osoby i zawiera ona Genderkolumnę. Możesz zapisać wartości jako „Mężczyzna” lub „Kobieta”. Jeśli użytkownik może zdecydować o nieudostępnianiu danych dotyczących płci, należy zapisać to jako NULL(tj. Użytkownik nie podał wartości), a nie pusty ciąg znaków (ponieważ nie ma płci o wartości „”).

Gan
źródło
7
Jeśli użytkownik zdecyduje się nie podawać płci, z pewnością należy zapisać „Odmowa podania”. NULL jest niejednoznaczny; może to również oznaczać „klient nie został zapytany”, „klient identyfikuje się z płcią, której nie ma na naszej liście” itp.
Jon z All Trades
8

Jedną rzeczą, o której warto pamiętać, jest to, że gdy masz pole, które nie jest wymagane, ale wszystkie obecne wartości muszą być unikalne, będziesz musiał przechowywać puste wartości jako NULL. W przeciwnym razie będziesz mieć tylko jedną krotkę z pustą wartością w tym polu.

Istnieją również pewne różnice w algebrze relacyjnej i wartościach NULL: na przykład NULL! = NULL.

Matthew Schinckel
źródło
4
W rzeczywistości nie jest tak, że NULL! = NULL, ponieważ to jest NULL. ;-)
Peter Eisentraut
1
Zauważ, że MS SQL nie przestrzega tej zasady: wiele wartości NULL naruszy UNIQUEograniczenie. Na szczęście, począwszy od 2008 roku, można użyć filtrowanego indeksu, aby uzyskać prawidłowe zachowanie.
Jon of All Trades,
4

Nowa myśl, duży wpływ na wybór NULL/ NOT NULLdotyczy tego, czy używasz frameworka. Używam dużo symfony i używanie NULLpól zezwalających upraszcza sprawdzanie kodu i danych podczas manipulowania danymi.

Jeśli nie używasz frameworka lub używasz prostych instrukcji SQL i przetwarzania, wybrałbym wybór, który Twoim zdaniem jest łatwiejszy do śledzenia. Zazwyczaj wolę NULL, aby wykonywanie INSERTinstrukcji nie było uciążliwe, gdy zapomniałem ustawić puste pola na NULL.

Patrick
źródło
pytanie dotyczy wartości NULL vs. pusty ciąg (w kolumnie null, IMO), a nie NULL vs NOT NULL, prawda?
Gan
część pytania o przechowywanie sprawiła, że ​​pomyślałem, że on również może myśleć o Null / Not Null
Patrick
lub @ ktokolwiek inny odnośnie implikacji NULL vs NOT NULL, możesz odnieść się do tego: dba.stackexchange.com/q/63/107
Gan
2

Po pracy z Oracle ( co nie pozwala na rozróżnienie ) doszedłem do następującego wniosku:

  • Z logicznego POV to nie ma znaczenia. Naprawdę nie mogę wymyślić przekonującego przykładu, w którym rozróżnienie między ciągiem NULL a ciągiem o zerowej długości dodaje jakąkolwiek wartość w DBMS.

  • Z czego wynika: albo masz NULLkolumnę zdolną, która nie pozwala zerowej wartości ''(rozwiązanie Oracle) lub NOT NULLkolumnę, która pozwala zerowej wartości.

  • Z mojego doświadczenia wynika, że ​​przetwarzanie danych ''ma o wiele większy sens, ponieważ normalnie chcesz przetwarzać brak ciągu jako pusty ciąg: Łączenie, porównywanie itp.

Uwaga: Aby wrócić do mojego doświadczenia z Oracle: Powiedz, że chcesz wygenerować zapytanie dotyczące żądania wyszukiwania. Jeśli używasz '', możesz po prostu wygenerować WHERE columnX = <searchvalue>i będzie działać dla wyszukiwania równości. Jeśli używasz NULL, musisz zrobić WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Bah! :-)

Jaskółka oknówka
źródło
2

Różnią się także od perspektywy projektowania:

na przykład

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

Wygląda jak:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

Pozwala wstawić niektóre dane:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

Teraz spróbujmy z zerowym:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

To jest dozwolone.

Soooooo: wartości null nie są trywialnymi łańcuchami ani odwrotnością.

Twoje zdrowie

Guy Birkbeck
źródło
1

Jeśli mówimy o teorii, wówczas zasady Codda mówią, że RDBMS musi traktować NULLwartości w specjalny sposób.

To, jak dokładnie to zostanie zastosowane, zależy od architektów baz danych, w zależności od faktycznej dziedziny - zadania - projektu - aplikacji - obszaru.

noonex
źródło