30.12.2013, Vladimír Klaus, navštíveno 5098x
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