it-swarm-eu.dev

SQL: prázdný řetězec vs. hodnota NULL

Vím, že toto téma je trochu kontroverzní a kolem internetu se vznáší spousta různých článků/názorů. Bohužel většina z nich předpokládá, že osoba neví, jaký je rozdíl mezi NULL a prázdným řetězcem. Takže vyprávějí příběhy o překvapivých výsledcích s připojením/agregáty a obecně dělají trochu pokročilejší lekce SQL. Tímto způsobem naprosto chybí celý bod, a jsou proto pro mě k ničemu. Doufejme, že se tato otázka a všechny odpovědi posunou o trochu vpřed.

Předpokládejme, že mám tabulku s osobními údaji (jméno, narození atd.), Kde jedním ze sloupců je e-mailová adresa s typem varchar. Předpokládáme, že z nějakého důvodu někteří lidé možná nebudou chtít poskytnout e-mailovou adresu. Při vkládání takových dat (bez e-mailu) do tabulky jsou k dispozici dvě možnosti: nastavit buňku na NULL nebo nastavit na prázdný řetězec (''). Předpokládejme, že jsem si vědom všech technických důsledků výběru jednoho řešení před druhým a mohu vytvořit správné dotazy SQL pro oba scénáře. Problém je, i když se obě hodnoty liší na technické úrovni, jsou na logické úrovni úplně stejné. Poté, co jsem se podíval na NULL a '', dospěl jsem k jedinému závěru: neznám e-mailovou adresu toho chlapa. Také bez ohledu na to, jak jsem se snažil, nemohl jsem poslat e-mail pomocí NULL nebo prázdného řetězce, takže většina serverů SMTP tam zjevně souhlasí s mou logikou. Takže mám tendenci používat NULL, kde neznám hodnotu a považuji prázdný řetězec za špatnou věc.

Po intenzivních rozhovorech s kolegy jsem přišel se dvěma otázkami:

  1. mám pravdu v předpokladu, že použití prázdného řetězce pro neznámou hodnotu způsobuje, že databáze „lže“ o faktech? Abych byl přesnější: pomocí SQL představy o tom, co je hodnota a co ne, mohl bych dojít k závěru: máme e-mailovou adresu, pouze tím, že zjistíme, že není null. Ale pak později, když se pokouším poslat e-mail, dospěju k protichůdnému závěru: ne, nemáme e-mailovou adresu, že @! # $ Databáze musela ležet!

  2. Existuje nějaký logický scénář, ve kterém by prázdný řetězec mohl být tak dobrým nosičem důležitých informací (kromě hodnoty a bez hodnoty), které by bylo obtížné/neefektivní ukládat jiným způsobem (jako je další sloupec). Viděl jsem mnoho příspěvků s tvrzením, že někdy je dobré použít prázdný řetězec spolu se skutečnými hodnotami a NULL, ale zatím jsem neviděl scénář, který by byl logický (z hlediska návrhu SQL/DB).

P.S. Někteří lidé budou v pokušení odpovědět, že je to jen otázka osobního vkusu. Nesouhlasím. Pro mě je to rozhodnutí o designu s důležitými důsledky. Takže bych rád viděl odpovědi, kde je opion o tom podložen logickými a/nebo technickými důvody.

73
Jacek Prucia

Řekl bych, že NULL je správnou volbou pro „no email address“. Existuje mnoho „neplatných“ e-mailových adres a „“ (prázdný řetězec) je pouze jedna. Například „foo“ není platná e-mailová adresa, „a @ b @ c“ není platná a tak dále. Jen proto, že „“ není platná e-mailová adresa, není důvod jej používat jako hodnotu „žádná e-mailová adresa“.

Myslím, že máte pravdu, když říkáte, že „“ není správný způsob, jak říci „Nemám hodnotu pro tento sloupec“. "" je hodnota.

Příkladem, kde "" může být platná hodnota, oddělené od NULL může být prostřední jméno osoby. Ne každý má prostřední jméno, takže musíte rozlišovat mezi „bez středního jména“ („“ - prázdný řetězec) a „nevím, jestli má tato osoba prostřední jméno nebo ne“ (NULL ). Pravděpodobně existuje mnoho dalších příkladů, kde prázdný řetězec je stále platnou hodnotou pro sloupec.

84
Dean Harding

Souhlasím s výše uvedenými poznámkami a dodal bych tento argument jako primární motivaci:

  1. Jakýkoli programátor, který se dívá na databázi, je zřejmé, že pole označené NULL je volitelné pole. (tj. záznam nevyžaduje údaje pro tento sloupec)
  2. Pokud označíte pole NOT NULL, měl by jakýkoli programátor intuitivně předpokládat, že se jedná o povinné pole.
  3. V poli, které umožňuje nuly, by programátoři měli očekávat, že uvidí nulové hodnoty, nikoli prázdné řetězce.

Pro intuitivní kódování samokokumentování použijte místo prázdných řetězců NULL.

41
colinbashbash

Ve vašem příkladu, pokud je to hodnota přímo z webového pole - použil bych prázdný řetězec. Pokud by uživatel mohl určit, že nechce e-mail poskytovat, nebo jej mohl smazat - pak NULL.

Zde je odkaz na body, které byste mohli zvážit: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945

--- upraveno (V reakci na Thomasův komentář) ---

Databáze nežijí bez aplikací, které je používají. Definování NULL nebo '' nemají žádnou hodnotu, pokud je aplikace nemůže správně použít.

Vezměme si jeden příklad, kde uživatel vyplňuje DLOUHÝ formulář a stiskl Enter, který pošle přetrvávající požadavek na server. Mohl být uprostřed zadávání e-mailu. Nejspíš budete chtít uložit cokoli, co má, do e-mailového pole, takže to později mohl dokončit. Co kdyby zadal pouze jednu postavu? Co kdyby zadal jednu postavu a pak ji smazal? Pokud e-mail není vyžadován, uživatelé jej někdy chtějí odstranit: nejjednodušší způsob, jak jednoduše vymazat pole. Také v případě, že e-mail není vyžadován, je vhodné jej před odesláním ověřit.

Jiný příklad: uživatel poskytuje e-mail jako spamto [[bigcompany] .com - v tom případě není třeba odesílat e-maily, i když existuje a je platný (a může dokonce existovat). Odeslání jednoho takového možná levného, ​​ale pokud existuje 10 000 uživatelů s takovými e-maily pro denní předplatné, pak může takové ověření ušetřit spoustu času.

6

Použijte Null.

Nemá smysl ukládat hodnotu '', když to jednoduše učiní tím, že se pole v tabulce zruší. Také jsou dotazy jasnější.

Který dotaz SQL je jasnější a čitelnější, pokud chcete najít uživatele s e-mailovou adresou?

  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

Řekl bych, že 2 je. Přestože je 3 robustnější v případech, kdy jsou uložena špatná data.

Pokud jde o e-mailovou adresu ve formuláři, která je volitelná, měla by se také promítnout do tabulky. V SQL je to pole s nulováním, což znamená, že není známo.

Nedokážu vymyslet žádnou rozumnou obchodní hodnotu při ukládání prázdného řetězce v tabulce, než jednoduše špatný design. Je to jako ukládat hodnotu řetězce 'NULL' nebo 'BLANK' a mít vývojáře předpokládej, že je nulová nebo prázdný řetězec. To je pro mě špatný design. Proč to ukládat, když je NULL ??

Stačí použít NULL a vy budete všichni trochu šťastnější.

VÍCE INFO:

SQL používá logický systém se třemi hodnotami: True, False a Unknown.

Pro lepší a podrobnější vysvětlení doporučuji vývojářům, aby si přečetli: SQL dotazy - nad TRUE a FALSE .

5
spong

Oracle bohužel zaměňoval reprezentaci řetězce VARCHAR o nule s reprezentací NULL. Oba jsou interně reprezentovány jedním bajtem s hodnotou nula. Díky tomu je diskuse mnohem těžší.

Mnoho zmatků obklopujících NULL se soustředí kolem logika se třemi hodnotami. Zvažte následující pseudokód:

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

Nečekali byste třetí zprávu, ale to je to, co byste dostali, pod logikou tří cen. Tři hodnotné logiky vedou lidi k četným chybám.

Dalším zdrojem zmatku je kresba závěrů z neexistence dat, jako kresba závěru od psa, který v noci neštěkal. Tyto závěry často nebyly tím, co autor NULL zamýšlel prozkoumat.

Přesto existuje spousta situací, kdy NULL zpracovává nepřítomnost dat v pořádku a vytváří přesně požadované výsledky. Jedním příkladem jsou cizí klíče ve volitelných vztazích. Pokud pomocí NULL označíte žádný vztah v daném řádku, tento řádek vypadne z vnitřního spojení, jak byste očekávali.

Také si uvědomte, že i když se NULLS úplně vyhnete v uložených datech (šestý normální tvar), pokud provedete vnější spojení, budete se stále muset vypořádat s NULLS.

5
Walter Mitty

Myslím, že odpověď Dean Hardingsa to opravdu pěkně pokrývá. To znamená, že bych rád zmínil, že když mluvíme o řetězcích NULL vs prázdné řetězce na úrovni DB, měli byste přemýšlet o svých dalších typech dat. Uložili byste minimální datum, když není dodáno žádné datum? nebo -1, pokud není dodáván žádný int? Uložení hodnoty, když nemáte žádnou hodnotu, znamená, že musíte sledovat celou škálu nehodnot. Alespoň jeden pro každý typ dat (možná více, jak se dostanete v případech, kdy -1 je skutečná hodnota, takže musíte mít nějakou alternativní atd.). Pokud potřebujete/chcete udělat něco „chmurného“ na aplikační úrovni, je to jedna věc, ale není třeba znečišťovat vaše data.

5
bendemes

pro konkrétní technickou otázku není problém null vs. prázdný řetězec, jedná se o selhání ověření. Prázdný řetězec není platná e-mailová adresa!

pro filosofickou otázku je odpověď podobná: ověřte své vstupy. Pokud je prázdný řetězec platnou hodnotou pro dané pole, pak jej očekávejte a kódujte; pokud ne, použijte null.

Prázdný řetězec by byl platným vstupem pro zodpovězení otázky: Co říkali žirafí mimi?

3
Steven A. Lowe

Dokázal jsem vymyslet důvod, proč mít NULL a prázdný řetězec:

  • Máte platné e-mailové adresy: [email protected]
  • Nemáte žádné (a pravděpodobně byste o ně měli požádat): NULL
  • Víte, že tato osoba nemá e-mailovou adresu: Empty String.

Nedoporučoval bych to a použijte samostatné pole pro otázku, zda víte, že žádné neexistuje.

2
Marcel

Otázka, jak tomu rozumím, je, jaké interpretace NULL a prázdného řetězce by měly být vybrány. Závisí to na tom, kolik stavů může být v poli partualar.

Interpretace závisí na způsobu přístupu k databázi. Pokud je v kódu vrstva, která zcela vyčerpává databázi, pak je výběr přijatelné zásady (včetně dvou-coulmn), který funguje, zcela přijatelný. (Jasné dokumentování politiky je však důležité). Pokud se však k databázi přistupuje na několika místech, měli byste použít velmi jednoduché schéma, protože kód bude obtížnější udržovat a v tomto případě může být chybný.

1
apoorv020

V zásadě na logické úrovni neexistuje žádný rozdíl mezi „neplatnou“ hodnotou a „žádným vstupem uživatele“, většinou jde jen o „zvláštní případy“. Případ chyby.

Mít null zabírá přídavný prostor: ceil (column_with_null/8) v bytech/na řádek.

Prázdná buňka i null jsou oba způsoby, jak označit, že je něco špatně/mělo by být výchozí. Proč byste potřebovali 2 „špatné“ stavy? Proč používat NULL, pokud zabírají další místo a znamenají přesně to samé jako prázdné řetězce? To bude jen představovat zmatek a nadbytečnost, když máte dvě věci, které znamenají (to by mohlo znamenat) přesně stejné, je snadné zapomenout, že byste měli používat NULL namísto prázdných řetězců (pokud např. Uživatel vynechal některá pole).

A vaše data se mohou stát nepořádkem. V dokonalém světě byste řekl: „data budou vždy správná a budu si pamatovat“ ... ale když lidé musí pracovat v týmu a ne každý je přesně na vaší úrovni, není neobvyklé vidět KDE (aa. xx <> '' AND bb.zz IS NENÍ NULL)

Takže místo toho, abych opravoval členy mého týmu každý druhý den, prostě vymáhám jednoduché pravidlo. Žádné nulové hodnoty, NIKDY!

Počítání NON-NULL hodnot je rychlejší ... jednoduchá otázka je, za co byste to měli udělat?

1
Slawek

Mám sklon to prohlížet ne z pohledu DB, ale z pohledu programu. Vím, že tato otázka je pro kliknutí na SQL, ale opravdu, kolik uživatelů přistupuje k datům již déle?

V programu se mi nelíbí null/nic. Existuje několik výjimek, ale to je jen to. A tyto výjimky jsou opravdu jen špatné implementace.

Pokud tedy uživatel do e-mailu nevložil, mělo by existovat něco, co určuje, zda je to platné nebo ne. Pokud je prázdný e-mail v pořádku, zobrazí se prázdný řetězec. Pokud uživatel nevložil e-mail a to porušuje pravidlo, měl by to objekt označit.

Myšlenka nulového významu je stará škola a je něco, co musí moderní programátoři obejít.

Dokonce ani v návrhu DB nemůže pole e-mailů povolit hodnoty null a mít řetězec nulové délky a mít další pole označující, zda uživatel něco zadal? Je o tolik tolik žádat DBMS? DB by podle mého názoru neměla zpracovávat ani obchodní logiku, ani logiku zobrazení. To nebylo postaveno pro to, a tak dělá velmi špatnou práci při manipulaci.

1
ElGringoGrande