Wiem, że ten temat jest nieco kontrowersyjny i po Internecie płynie wiele różnych artykułów / opinii. Niestety większość z nich zakłada, że osoba nie wie, jaka jest różnica między NULL a pustym ciągiem. Opowiadają więc historie o zaskakujących wynikach z łączeniami / agregacjami i generalnie robią nieco bardziej zaawansowane lekcje SQL. Robiąc to, absolutnie nie rozumieją sedna i dlatego są dla mnie bezużyteczne. Mam nadzieję, że to pytanie i wszystkie odpowiedzi posuną temat nieco do przodu.
Załóżmy, że mam tabelę z danymi osobowymi (imię i nazwisko, urodzenie itp.), W której jedną z kolumn jest adres e-mail z typem varchar. Zakładamy, że z jakiegoś powodu niektóre osoby mogą nie chcieć podać adresu e-mail. Podczas wstawiania takich danych (bez wiadomości e-mail) do tabeli dostępne są dwie opcje: ustaw komórkę na NULL lub ustaw pusty ciąg (''). Załóżmy, że znam wszystkie techniczne implikacje wyboru jednego rozwiązania zamiast drugiego i mogę utworzyć poprawne zapytania SQL dla każdego scenariusza. Problem występuje nawet wtedy, gdy obie wartości różnią się na poziomie technicznym, są dokładnie takie same na poziomie logicznym. Po spojrzeniu na NULL i „” doszedłem do jednego wniosku: nie znam adresu e-mail faceta. Nie ważne jak bardzo się starałem, Nie mogłem wysłać wiadomości e-mail przy użyciu wartości NULL lub pustego ciągu, więc najwyraźniej większość serwerów SMTP zgadza się z moją logiką. Więc zwykle używam NULL, gdy nie znam wartości i uważam pusty ciąg za złą rzecz.
Po kilku intensywnych rozmowach z kolegami zadałem dwa pytania:
czy mam rację, zakładając, że użycie pustego łańcucha dla nieznanej wartości powoduje, że baza danych „kłamie” na temat faktów? Mówiąc ściślej: korzystając z idei SQL, co jest wartością, a co nie, mogę dojść do wniosku: mamy adres e-mail, po prostu odkrywając, że nie jest on zerowy. Ale później, próbując wysłać e-mail, dochodzę do sprzecznego wniosku: nie, nie mamy adresu e-mail, że @! # $ Baza danych musiała kłamać!
Czy istnieje logiczny scenariusz, w którym pusty ciąg „” mógłby być tak dobrym nośnikiem ważnych informacji (oprócz wartości i bez wartości), co byłoby kłopotliwe / nieefektywne do przechowywania w jakikolwiek inny sposób (np. Dodatkowa kolumna). Widziałem wiele postów stwierdzających, że czasami warto używać pustych ciągów wraz z rzeczywistymi wartościami i wartościami NULL, ale jak dotąd nie widziałem scenariusza, który byłby logiczny (pod względem projektu SQL / DB).
PS Niektórzy ludzie będą mieli ochotę odpowiedzieć, że to kwestia osobistego gustu. Nie zgadzam się Dla mnie jest to decyzja projektowa z ważnymi konsekwencjami. Chciałbym więc zobaczyć odpowiedzi, w których opozycja na ten temat jest poparta logicznymi i / lub technicznymi przyczynami.
''
nawet w Oracle, to nie to samo coNULL
. Na przykład przypisanieCHAR(1)
kolumny wartości''
spowoduje' '
(tj. Spację), a nieNULL
. Poza tym, gdyby Jacek używał Oracle, to pytanie prawdopodobnie nawet nie pojawiłoby się :-)'' IS NULL
ewaluujetrue
w PL / SQL.Odpowiedzi:
Powiedziałbym, że
NULL
jest to właściwy wybór dla „brak adresu e-mail”. Istnieje wiele „nieprawidłowych” adresów e-mail, a „” (pusty ciąg) to tylko jeden. Na przykład „foo” nie jest prawidłowym adresem e-mail, „a @ b @ c” jest nieprawidłowe i tak dalej. Dlatego, że „” nie jest prawidłowym adresem e-mail, nie ma powodu, aby używać go jako wartości „brak adresu e-mail”.Myślę, że masz rację mówiąc, że „” nie jest poprawnym sposobem powiedzenia „Nie mam wartości dla tej kolumny”. „” to wartość.
Przykładem tego, gdzie „” może być prawidłową wartością, oddzielne od
NULL
może być drugie imię osoby. Nie każdy ma drugie imię, więc musisz odróżnić „brak drugiego imienia” („” - pusty ciąg znaków) od „Nie wiem, czy ta osoba ma drugie imię, czy nie” (NULL
). Prawdopodobnie istnieje wiele innych przykładów, w których pusty ciąg jest nadal prawidłową wartością dla kolumny.źródło
NULL
nie oznacza to, że nie ma adresu e-mail, myślę, że oznacza to, że adres e-mail nie jest obecnie znany, nie istnieje lub nie można go wypełnić z innych powodów. Na szczęście prawdopodobnie nie ma sytuacji, w której ktoś chciałby przechowywać w bazie danych informacje o ludziach, którzy naprawdę nie mają i nie planują posiadania adresu e-mail, w przeciwnym razie prawdopodobnie konieczne byłoby oddzielne pole logiczne.Zgadzając się z powyższymi komentarzami, chciałbym dodać ten argument jako główną motywację:
Ze względu na samodokumentujące intuicyjne kodowanie należy użyć NULL zamiast pustych ciągów.
źródło
W twoim przykładzie, jeśli jest to wartość bezpośrednio z pola internetowego - użyłbym pustego ciągu. Jeśli użytkownik może określić, że nie chce podawać wiadomości e-mail, lub może ją usunąć - to NULL.
Oto link do punktów, które możesz wziąć pod uwagę: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945
--- edytowane (w odpowiedzi na komentarz Thomasa) ---
Bazy danych nie działają bez aplikacji, które ich używają. Definiowanie wartości NULL lub „” nie ma wartości, jeśli aplikacja nie może jej poprawnie użyć.
Rozważ jeden przykład, w którym użytkownik wypełnia DŁUGI formularz i naciśnij Enter, który wyśle żądanie trwałego do serwera. Mógł być w trakcie wprowadzania swojego adresu e-mail. Najprawdopodobniej chcesz przechowywać wszystko, co ma w polu e-mail, aby później mógł to zakończyć. Co jeśli wprowadzi tylko jedną postać? Co jeśli wprowadzi jeden znak, a następnie go usunie? Gdy wiadomość e-mail nie jest wymagana, czasami użytkownicy chcą ją usunąć: najłatwiejszy sposób na wyczyszczenie pola. Również w przypadku, gdy wiadomość e-mail nie jest wymagana, warto ją zweryfikować przed wysłaniem.
Kolejny przykład: użytkownik podaje wiadomość e-mail jako spamto @ [duża firma] .com - w takim przypadku nie ma potrzeby wysyłania wiadomości e-mail, nawet jeśli istnieje ona i jest ważna (a może nawet istnieć). Wysyłanie jednego takiego może być tanie, ale jeśli jest 10 000 użytkowników z takimi e-mailami do codziennych subskrypcji, taka weryfikacja może zaoszczędzić dużo czasu.
źródło
Myślę, że odpowiedź Dean Hardings naprawdę ładnie to obejmuje. To powiedziawszy, chciałbym wspomnieć, że mówiąc o wartościach NULL vs pustych ciągach na poziomie DB, powinieneś pomyśleć o innych typach danych. Czy zapisałbyś datę minimalną, gdy nie podano daty? lub -1, gdy nie podano int? Przechowywanie wartości, gdy nie masz żadnej wartości, oznacza, że musisz śledzić cały zakres wartości innych. Co najmniej jeden dla każdego typu danych (być może więcej, gdy dostaniesz przypadki, w których -1 jest wartością rzeczywistą, więc musisz mieć jakieś alternatywne itp.). Jeśli potrzebujesz / chcesz zrobić coś „zbędnego” na poziomie aplikacji, to jedno, ale nie ma potrzeby zanieczyszczania twoich danych.
źródło
Niestety Oracle pomyliło reprezentację ciągu VARCHAR o długości zero z reprezentacją NULL. Oba są wewnętrznie reprezentowane przez jeden bajt o wartości zero. To sprawia, że dyskusja jest o wiele trudniejsza.
Wiele zamieszania wokół NULL koncentruje się wokół logiki trójwartościowej . Rozważ następujący pseudokod:
Nie spodziewałbyś się trzeciej wiadomości, ale to byś otrzymał, pod logiką o trzech wartościach. Trzy ceniona logika prowadzi ludzi do licznych błędów.
Innym źródłem zamieszania jest wyciąganie wniosków z braku danych, takich jak wyciąganie wniosków z psa, który nie szczekał w nocy. Często te wnioski nie były tym, co zamierzał napisać NULL.
To powiedziawszy, istnieje wiele sytuacji, w których NULL dobrze radzi sobie z brakiem danych i daje dokładnie pożądane wyniki. Jednym z przykładów są klucze obce w relacjach opcjonalnych. Jeśli użyjesz NULL, aby wskazać brak relacji w danym wierszu, wiersz ten wypadnie z połączenia wewnętrznego, tak jak można się spodziewać.
Pamiętaj również, że nawet jeśli całkowicie unikniesz NULLS w przechowywanych danych (szósta postać normalna), jeśli wykonasz jakiekolwiek zewnętrzne sprzężenia, nadal będziesz musiał poradzić sobie z NULLS.
źródło
Użyj Null.
Nie ma sensu przechowywanie wartości „”, gdy wystarczy zrobić pole w tabeli, które ma wartość null. Sprawia to, że zapytania są bardziej oczywiste.
Które zapytanie SQL jest bardziej oczywiste i czytelne, jeśli chcesz znaleźć użytkowników z adresem e-mail?
SELECT * FROM Users WHERE email_address != ''
SELECT * FROM Users WHERE email_address IS NOT NULL
SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL
Powiedziałbym, że 2 to. Chociaż 3 jest bardziej niezawodny w przypadkach, w których przechowywane są złe dane.
W przypadku adresu e-mail w formularzu, który jest opcjonalny, należy go również uwzględnić w tabeli. W SQL jest to pole zerowalne, co oznacza, że nie jest znane.
Nie mogę wymyślić żadnej rozsądnej wartości biznesowej w przechowywaniu pustego łańcucha w tabeli innej niż po prostu zły projekt. To tak, jakby przechowywać wartość ciągu „NULL” lub „PUSTE”, a programiści zakładają , że jest to ciąg zerowy lub pusty. Dla mnie to zły projekt. Po co przechowywać to, gdy jest NULL?
Po prostu użyj NULL, a sprawisz, że wszyscy będą trochę bardziej szczęśliwi.
WIĘCEJ INFORMACJI:
SQL korzysta z trójwartościowego systemu logicznego: True, False i Unknown.
Aby uzyskać lepsze i bardziej szczegółowe wyjaśnienie, polecam programistom przeczytanie: Kwerendy SQL - poza PRAWDĄ i FAŁSZ .
źródło
w przypadku konkretnego pytania technicznego problem nie jest równy null vs pusty ciąg, jest to błąd sprawdzania poprawności . Pusty ciąg nie jest prawidłowym adresem e-mail!
w przypadku pytania filozoficznego odpowiedź jest podobna: zweryfikuj swoje dane wejściowe. Jeśli pusty ciąg jest poprawną wartością dla danego pola, należy się spodziewać i kod dla niego; jeśli nie, użyj null.
Pusty ciąg znaków byłby ważnym wkładem do odpowiedzi na pytanie: Co mim powiedział żyrafie?
źródło
Mógłbym wymyślić przyczynę posiadania wartości NULL i pustego ciągu:
[email protected]
NULL
Empty String.
Jednak nie zaleciłbym tego i użyj osobnego pola, aby zapytać, czy wiesz, że żadne nie istnieje.
źródło
Pytanie, jakie rozumiem, brzmi, które interpretacje NULL i pusty ciąg powinny zostać wybrane. Zależy to od tego, w ilu stanach może znajdować się dane pole.
Interpretacja zależy od sposobu dostępu do bazy danych. Jeśli w kodzie jest warstwa, która całkowicie wyodrębnia bazę danych, to wybór jakiejkolwiek polityki (w tym dwu-coulmn), która działa, jest całkowicie akceptowalny. (Jasne dokumentowanie zasad jest jednak ważne). Jeśli jednak dostęp do bazy danych jest uzyskiwany w kilku miejscach, powinieneś użyć bardzo prostego schematu, ponieważ kod będzie trudniejszy w utrzymaniu i może być w tym przypadku błędny.
źródło
Zasadniczo na poziomie logicznym nie ma różnicy między „nieprawidłową” wartością a „brakiem wprowadzania danych przez użytkownika”, są to po prostu wszystkie „przypadki szczególne” przez większość czasu. Przypadek błędu.
Posiadanie null zajmuje dodatkowe miejsce: ceil (columns_with_null / 8) w bajtach / na wiersz.
Pusta komórka i null są sposobem na oznaczenie, że coś jest nie tak / powinno być domyślne. Dlaczego potrzebujesz 2 „złych” stanów? Po co używać wartości NULL, jeśli zajmują dodatkowe miejsce i oznaczają dokładnie to samo, co puste ciągi znaków? To po prostu wprowadzi zamieszanie i nadmiarowość, gdy masz dwie rzeczy, które oznaczają (to może oznaczać) dokładnie to samo, łatwo zapomnieć, że powinieneś używać NULL zamiast pustych ciągów (jeśli np. Użytkownik pominął niektóre pola).
Twoje dane mogą stać się bałaganem. W idealnym świecie powiedziałbyś, że „dane będą zawsze poprawne, a ja zapamiętam” ... ale kiedy ludzie muszą pracować w zespole i nie wszyscy są dokładnie na twoim poziomie, nierzadko można zobaczyć GDZIE (aa. xx <> '' ORAZ bb.zz NIE JEST NULL)
Zamiast więc poprawiać członków mojego zespołu co drugi dzień, po prostu egzekwuję prostą zasadę. Brak wartości zerowych, NIGDY!
Liczenie wartości NON-NULL jest szybsze ... proste pytanie, po co byś to zrobił?
źródło
VARCHAR
kolumna zajmie co najmniej 1 bajt, aby zapisać długość łańcucha, nawet jeśli wynosi zero.Zwykle patrzę na to nie z perspektywy DB, ale z perspektywy programu. Wiem, że to pytanie dotyczy kliknięcia SQL, ale tak naprawdę, ilu użytkowników ma bezpośredni dostęp do danych?
W programie nie lubię null / nothing. Jest kilka wyjątków, ale one są po prostu takie. A te wyjątki są naprawdę po prostu złymi implementacjami.
Jeśli więc użytkownik nie podał adresu e-mail, powinno być coś, co określa, czy jest to poprawne, czy nie. Jeśli pusty e-mail jest w porządku, wyświetla pusty ciąg. Jeśli użytkownik nie podał wiadomości e-mail, co narusza regułę, obiekt powinien to zaznaczyć.
Idea zerowego znaczenia ma charakter starej szkoły i jest czymś, nad czym muszą pracować nowi programiści.
Nawet w projekcie DB, dlaczego pole e-mail nie pozwala na wartości zerowe i ma ciąg o zerowej długości oraz inne pole wskazujące, czy użytkownik coś wprowadził? Czy można zapytać o DBMS o tyle? Moim zdaniem DB nie powinien obsługiwać ani logiki biznesowej, ani logiki wyświetlania. Nie został stworzony do tego, a zatem bardzo źle sobie z tym radzi.
źródło
Nie sądzę, żeby miało to duże znaczenie, ale bardziej podoba mi się, gdy jest tam NULL.
Kiedy przeglądam dane wyświetlane w tabeli (jak w SQL Server Management Studio), mogę lepiej odróżnić brakującą wartość, jeśli jest napisane NULL, a tło ma inny kolor.
Jeśli widzę puste miejsce, zawsze zastanawiam się, czy jest naprawdę puste, czy jest jakaś biała spacja lub jakieś niewidzialne znaki. Z NULL jest gwarantowana pusta na pierwszy rzut oka.
Zwykle nie rozróżniam wartości w aplikacji, ponieważ jest nieoczekiwane i dziwne, że NULL i pusty ciąg znaków oznaczają coś innego. Przez większość czasu podchodzę do defensywy i po prostu mam do czynienia z obydwoma stanami. Ale dla mnie, jako człowieka, NULL jest łatwiejszy do przetworzenia, patrząc na dane.
źródło