Danas je na Pollitici pokrenuta tema o manipulaciji popisima birača. Na stranici Pretraživanje popisa birača možete provjeriti koliko na pojedinoj adresi ima birača. Sumnjive su adrese koje po pravilu imaju kućni broj 0 ili 900 i veći. Svi oni koji imaju iskustva s bilo kakvim komunalnim sustavima već pogađaju zbog čega su se pojavili ti nerealni brojevi. U pravilu se radi o adresama bez kućnog broja pa se u tom slučaju upisivala nula (broj 0) ili neki veliki broj (u ovom slučaju 900).
Sve to ne bi bilo dovoljan razloga za ovaj post da u navedenoj temi komentator petar8 nije ustvrdio da je logičan pristup po kojem se upisuje broj 0 tamo gdje ne postoji kućni broj. Na komentar da se u tom slučaju koristi NULL petar8 odgovara ali je pravilo da se null izbjegava - jer inače svako pretraživanje traži uzimanje u obzir da navedeno polje nema vrijednosti....
Ups...NULL se izbjegava zato da programer u pojedinim slučajevima ne bi trebao pisati dodatni uvjet u upit? To nije pravilo, to je glupost i lijenost i kosi se s još uvijek važećim pravilima za RDBMS-ove. Ima NULL svojih nedostataka, ima prijedloga koji bi te nedostatke mogli ukloniti, ali kako oni još nisu postali standard moramo se ravnati po starom standardu. Edgar F. Codd (18.4. mu je 6. godišnjica smrti) je tu bio poprilično jasan. NULL rješava potrebu da se u bazi prikažu informacije koje nedostaju ili nisu poznate. U spomenutom slučaju kućni broj nije poznat pa je jedino logično rješenje da se on označi kao NULL (nepoznat, bez vrijednosti).
Zašto programeri izbjegavaju NULL? Uglavnom zato jer u upitima zaboravljaju obraditi to nedostajanje vrijednosti, dobivaju neočekivane rezultate pa idu linijom manjeg otpora i koriste nulu ili prazan string. Dodatan problem predstavljaju i različite implementacije u pojedinim bazama. Npr. ako imate ORDER BY po polju koje može imati i NULL vrijednosti (npr. tablica natjecatelja koja ima polje pozicija koje neće imati vrijednost ako natjecatelj nije završio utrku ) Microsoft SQL Server će vam te natjecatelje s NULL pozicijom postaviti ispred natjecatelja s pozicijama, dok će Oracle i PostgreSQL te natjecatelje staviti iza natjecatelja koji imaju konkretnu vrijednost u polju pozicija.
NULL se koristi, i polje u tablici se označava da može imati NULL vrijednost, u slučaju kad postoji potreba da se slog spremi bez da je poznata vrijednost u tom ili takvim poljima. U navedenom slučaju s natjecateljima mi moramo biti svjesni da postoje oni koji nisu osvojili poziciju u utrci i oni imaju drugi status nego natjecatelji koji su utrku završili. Aplikacija koja bi obrađivala rezultate mora biti svjesna toga, a ne da zanemaruje problem koristeći nulu ili neki veliki broj. Izbjegavanje NULL-a može se u nekim slučajevima vratiti kao bumerang jer će programer na kraju pisati više koda nego da ga je koristio.
Primjer koji sam ja navodio, kad sam nedavno dokazivao da postoje slučajevi kad se NULL treba koristiti, je slučaj tablice u kojoj se sprema datum nečije smrti (npr. baza za udrugu za posmrtnu pripomoć). U toj tablici su navedeni i živi ljudi koji još nemaju datum smrti. Što će oni, kojima je logično da se NULL izbjegava, upisati u to polje? Neki nerealni datum? Bez obzira koliko taj datum bio daleko, nekima se ne bi dopalo da predviđate datum njihove smrti. Zanima vas popis živih članova? Ako ste usvojili petar8 logiku onda morate znati koji vam je granični datum pa su živi oni koji imaju taj granični datum. Ako se držite standarda onda su vam živi svi oni koji nemaju datum smrti. Što je logičnije?
Neki ne vole NULL-ove zato jer skoro sve funkcije za agregaciju ignoriraju NULL-ove. Zamislimo da je petar8 radio aplikaciju koja bilježi temperaturu u gradu i na temelju prikupljenih podataka vraća prosječnu temperaturu. Postoje dani kad temperatura iz nekog razloga nije očitana. Slog s tim datumom će imati NULL u polju temperatura. petar8 i njegova logika će se u tom slučaju imati problem jer ne mogu koristiti nulu (budući da regularna temperatura može imati tu vrijednost) pa će najvjerojatnije uzeti neku nerealnu vrijednost. -100 ili 100?! Kod ispisa prosječnih temperatura petar8 će dobiti čudne vrijednosti, pa će se sjetiti da mora dodati uvjet kako bi isključio dane kada nije bilo očitavanja. Oni koji su koristili NULL tih problema nemaju jer funkcija AVG isključuje takve podatke.
Budite oprezni u logičnom izbjegavanju NULL-ova. Možda jednog dana zaslužite svojih pet minuta slave na The Daily WTF portalu. ;-)
Jedan od razllga ovakvih problema je što se (zbog štednje, ali i neznanja) pisanjem SQL upita i procedura bave oni developeri koji pišu i osnovni kod, a najčešće im je znanje SQL-a vrlo bazično i nekompletno. Idealno bi bilo -- barem kad je riječ o većim i kritičnijim aplikacijama (kao što je popis birača) -- imati posebnog SQL developera koji će znati što kada i zašto upotrijebiti. Programer poslovne logike tada ne mora uopće brinuti o tome što mu baza šalje, jer dobiva već pročišćene i jasno definirane podatke.