30. 12. 2013, Vladimír Klaus, přečteno 3550x
Předpokládejme, že si chcete napsat funkci, která pomocí SQL dotazu vrátí součet cen.
Vycházíme přitom z dat této tabulky.
Není to nic těžkého, na to máme funkci QueryValue, takže funkce by mohla vypadat takto.
//první jednoduchá verze a) public static decimal MujSoucet1() { var db = Database.Open("Data"); var selectQueryString = "SELECT SUM(Cena) FROM MojeTabulka WHERE ID <= 2"; var res = db.QueryValue(selectQueryString); return res; }
Funkce vrátí 500. Skvělé, funguje to! Nyní změníme podmínku na ID > 2;
//první jednoduchá verze b) public static decimal MujSoucet1() { var db = Database.Open("Data"); var selectQueryString = "SELECT SUM(Cena) FROM MojeTabulka WHERE ID > 2"; var res = db.QueryValue(selectQueryString); return res; }
Výsledkem je ale chyba. Ceny v záznamech jsou NULL, že by to bylo tím?
Dobrá tedy, upravíme dotaz tak, aby si s takovou situací poradil a budeme NULL hlídat. Vždyť přece součet NULL je také NULL.
//druhá, o něco chytřejší verze public static decimal MujSoucet2() { var db = Database.Open("Data"); var selectQueryString = "SELECT SUM(Cena) FROM MojeTabulka WHERE ID > 2"; var res = db.QueryValue(selectQueryString); if(res != null) { return res; } else { return 0; } }
Jenže ono to zase neprojde. Proč? Asi by to chtělo si lépe přečíst onu chybu. Vrací totiž informaci o DBNull, nikoliv NULL.
Takže jak budeme testovat na DBNull? Úplně jinou funkcí. A také upravíme návratovou hodnotu třeba na -1 (může se to hodit), protože i součet cen může být 0 a nemohli bychom to odlišit od situace, kdy je to opravdu NULL.
//třetí a nejchytřejší verze? public static decimal MujSoucet3() { var db = Database.Open("Data"); var selectQueryString = "SELECT SUM(Cena) FROM MojeTabulka WHERE ID > 2"; var res = db.QueryValue(selectQueryString); if(DBNull.Value.Equals(res)) { return -1; } else { return res; } }
Jak asi vidíte z příkladu, stejně není možné odlišit situaci, kdy záznamy existují, ale součet vrací NULL od situace, kdy žádné takové záznamy neexistují. Řešením mohou být dva dotazy.
//čtvrtá úplně dokonalá verze public static decimal MujSoucet4(int IDVetsiNez) { var db = Database.Open("Data"); var selectQueryString = "SELECT COUNT(*) FROM MojeTabulka WHERE ID > @0"; var res = db.QueryValue(selectQueryString, IDVetsiNez); if(res != 0) { selectQueryString = "SELECT SUM(Cena) FROM MojeTabulka WHERE ID > @0"; var resval = db.QueryValue(selectQueryString, IDVetsiNez); if(DBNull.Value.Equals(resval)) { //záznamy existují, ale VŠECHNY jejich ceny jsou NULL return -1; } else { //záznamy existují a bylo možné ceny (některé mohou být NULL) sečíst return resval; } } else { //žádné záznamy neexistují, na sčítání vůbec nedojde! return -999; } }
Při volání s různými parametry...
<p>Součet cen: @MujSoucet4(0)</p>
<p>Součet cen: @MujSoucet4(2)</p>
<p>Součet cen: @MujSoucet4(30)</p>
...získáme již zcela korektní výsledek.
Součet cen: 500
Součet cen: -1
Součet cen: -999
Tweet