Czy powinienem przechowywać wartość False jako Null w polu logicznej bazy danych?

20

Załóżmy, że masz aplikację o polu boolowskim w Usertabeli o nazwie Inactive.

Czy jest coś z natury złego w przechowywaniu fałszu jako wartości zerowej? Jeśli tak, czy możesz wyjaśnić, co powinno być wadą? Rozmawiałem o tym z kimś kilka miesięcy temu i oboje zgodziliśmy się, że nie powinno to mieć znaczenia, o ile konsekwentnie robisz to w całej aplikacji / bazie danych. Ostatnio ktoś, kogo znam, stanowczo podkreślił, że jest „prawdziwy” truelub falsepowinien zostać użyty, ale tak naprawdę nie wyjaśnił dlaczego.

Ominus
źródło
25
Wikipedia twierdzi, że Null is a special marker used in Structured Query Language (SQL) to indicate that a data value does not exist in the database jest to przyjęta mądrość i nie powinieneś redefiniować znaczenia Null w swojej aplikacji. Będzie to mylące dla wszystkich osób pracujących z twoim kodem.
PersonalNexus,
10
Dlaczego w ogóle CHCESZ to zrobić? Dlaczego po prostu nie użyć zerowego pola bitowego i ustawić domyślną wartość false, jeśli takie zachowanie jest pożądane, zamiast mylić problem z polem trójstanowym?
JohnFx,
5
Przykład, dlaczego jest to bardzo zły pomysł: SELECT * FROM foo WHERE bar = FALSEnie daje oczekiwanych rezultatów.
Blrfl,
2
Rozważ użycie kolumny int z domyślną wartością 0 zamiast wartości logicznej. W ten sposób, jeśli pojawią się nowe warunki (na przykład stan „w toku”), nie musisz zmieniać struktury bazy danych.
GrandmasterB,
4
Ale jeśli zapiszesz false jako zero, jak zamierzasz przechowywać FILE_NOT_FOUND ?! ( thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx )
Ed James

Odpowiedzi:

50

Czy jest coś z natury złego w przechowywaniu fałszu jako wartości zerowej?

Tak.

Jeśli tak, czy możesz wyjaśnić, co powinno być wadą?

NULL to nie to samo co Fałsz.

Z definicji porównania (i logika), które obejmują NULL, powinny zwracać wartości NULL (nie False). Jednak implementacje SQL mogą się różnić.

True and NULL ma wartość NULL (nie False).

True and NULL or False ma wartość NULL (nie False).

http://en.wikipedia.org/wiki/Null_(SQL)#Three-valued_logic_.283VL.29

http://technet.microsoft.com/en-us/library/cc966426.aspx

S.Lott
źródło
3
Dokładne wyjaśnienie, dlaczego NULL jest wartością reprezentującą brak wartości.
wałek klonowy
2
pierwszy dzień mojej pierwszej pracy programistycznej polegał na debugowaniu i naprawianiu błędu jak w tym pytaniu / odpowiedzi, wspomnienie +1
tsundoku
1
Zauważ, że sam artykuł, z którym się łączysz, mówi, że jeśli to nie nullma znaczenia dla logiki (jak ma to miejsce w przypadku whatever OR TRUElub whatever AND FALSE, gdy żadna wartość nie whatevermoże zmienić warunku), wówczas wyrażenie zwraca wartość. To nie jest optymalizacja; tak działa logika trójwartościowa . Każdy DBMS, który nalega na zwrot UNKNOWN/ NULLdla tych wyrażeń, jest zasadniczo uszkodzony.
cHao
1
@ S.Lott, ale nie przechowuje wartości null zamiast false, oszczędzasz trochę miejsca?
azerafati
2
@Bludream: W przypadku boolean pole zerowalne może faktycznie zająć więcej miejsca, w zależności od DBMS. (Jest to znikoma ilość w prawie wszystkich przypadkach, choć.) Wartość logiczna może być reprezentowany w jednym kawałku ... ale pustych logiczna ma trzy możliwe wartości (true, false i null), a zatem potrzebuje więcej niż jednego bitu.
cHao
15

Zezwalając na wartości null w polu logicznym, zamieniasz zamierzoną reprezentację binarną (prawda / fałsz) w reprezentację trójstanową (prawda, fałsz, null), w której twoje wpisy „null” są nieokreślone. Wartość „null” nie jest odpowiednio „prawdziwa” ani „fałszywa”. Jaki powód musiałbyś zwiększyć swoją reprezentację, aby była niedokładna?

Nawet jeśli zdecydujesz się na taki wzór i robisz to konsekwentnie przez całą aplikację, nie jest to w porządku. Skończysz w sytuacji, w której świeże oczy nie są jasne, dlaczego ten wzór jest na miejscu, lub, co bardziej prawdopodobne, skończysz w sytuacji, w której ten wzór zostanie przypadkowo złamany.

Jacob Maristany
źródło
5

Co powiedzieli inni. 3 możliwe wartości nie są wartością logiczną.

Ale możesz mieć uzasadnioną potrzebę 3 wartości. Takich jak (prawda, fałsz, nieznane). Nawet jeśli tak jest, jeśli jesteś w ultra-normalizacji, w ogóle nie zezwalasz na wartości zerowe. Zamiast tego będziesz przechowywać prawdziwą wartość logiczną w innej tabeli z relacją 1 do 1. Wartość null może zostać wygenerowana w zapytaniu przez „nieudane” połączenie zewnętrzne, a nie przez fizycznie zapisaną wartość null.

Lord Tydus
źródło
poza królestwem mojego logicznego pytania, dlaczego prawda fałszywa nieznana byłaby zła, gdybyś użył do tego wartości zerowej? Poza moim pytaniem, czy należy unikać wartości zerowych? Dlaczego?
Ominus,
3
@Ominus: Zasadniczo należy unikać zer, jeśli jesteś purystą. Jeśli są używane tak, jak powinny być używane (jako „nie ma tu żadnej wartości”, a nie jako fałszywe fałszywe false), to mają swoje miejsce. Gdyby nie, nie istnieliby. Alternatywą, jak wspomniano, jest zasadniczo posiadanie całej innej tabeli z tylko kluczem podstawowym wiersza i pojedynczą wartością logiczną (lub int, lub varchar lub co masz). Dla każdego pola, które w innym przypadku byłoby zerowane. Chociaż względnie czysty, jest zbyt zawiły dla większości celów.
cHao
-3

Czy bool?to typ boolowski? Nie, to jest typu Nullable<T>gdzie Tjest logiczna. Zerowalne boolean może mieć 3 wartości: true, false i null. Aby użyć boollub bool?zależy od wymagań. Może istnieć uzasadniony powód, dla którego może być konieczne użycie wartości null, ale typu, który pachnie jak binarny, ale nie znasz odpowiedzi. W powyższym przykładzieUser.IsActivewydaje się jasne. Użytkownik jest aktywny czy nie. Jako system może chcieć wiedzieć, czy użytkownik jest aktywny, czy nie. Nie powinno być „może”. Ale pomyśl o czymś takim jak flaga funkcji. Czy funkcja jest włączona? Odpowiedzi mogą być tak, nie lub niepewne. Możesz mieć regułę biznesową, która przeliteruje, że przycisk wyświetla się tylko wtedy, gdy flaga jest ustawiona na true. Można argumentować, że bool jest domyślnie fałszywy, więc po co tworzyć zerowalne bool? Odwróć wymaganie: czy ustawisz wszystkie wartości w źródle danych na true?

nullableTypes
źródło
2
ten post jest raczej trudny do odczytania (ściana tekstu). Czy mógłbyś edytować go w lepszym kształcie?
komara