On 5 Apr 2019, at 00:18, Simon Slavin <slav...@bigfraud.org> wrote: > > On 4 Apr 2019, at 10:12pm, Lifepillar <lifepil...@icloud.com> wrote: > >> This is essentially a pragmatic choice, as the semantics of NULLs is >> unspecified and ambiguous. > > The way SQL handles NULLs may sometimes appear inconsistent, but is the > result of SQL handling rows as sets. Some of the behaviour is, carefully > designed, with the knowledge that the NULL that results from one step of an > expression is going to be fed into the next step of the expression.
I beg to disagree. NULL's handling in SQL *is* inconsistent. The SQL committee has taken some actions to make things... less worse, in particular by adding F571 ("is true", "is false", "is unknown"), but the castle still remains (and will likely forever remain) a castle of sand. > For those purposes, NULL means one of two things: "no value" or "value > unknown”. There is a third option: “no information” (value may exist and be unknown, or it may not exist). And before someone asks: no, there is no need for going meta (“don’t know whether there is no information…”). > For instance, the sum of a result which includes a NULL value is NULL. Note that this is incompatible with the “value unknown” semantics (noticed in *1977* by Grant!). Trivial example: select * from T where x = x; If x contains NULLs, under the “value unknown” semantics the above query should still output all the rows, because an existing value, albeit unknown, is always, surely, equal to itself. Under the “inapplicable” semantics SQL's result is correct, though, and under the “no information” semantics it may be considered correct assuming that you want certain answers (i.e., only tuples that satisfy the condition with certainty). You see that NULL conflate different things and leaves the user the burden to deal with it. > But the sum of a result with zero rows is not NULL, it's zero. So, SQL is wrong there, because it returns NULL (my library returns 0). Note that an empty table has no NULLs, so the result of any query or function on an empty set has nothing to do with NULLs. I am fond of NULLs (as much as I try to avoid them in my databases), so if you feel like it is interesting discussing this any further (and deemed appropriate for the list), we may do so in a separate thread. > For the purposes of a decimal extension to SQLite, I would imitate what > SQLite3 does with REAL values. If you have a question about how SQLite sees > NULL it might be answered here: > > <https://sqlite.org/nulls.html> > > It's especially important that the test script at the end of that page, > behaves the same if you run it as is, and if you substitute the 'int' type > with your decimal type. If you have any questions, please don't hesitate to > ask.§ I have tried the script, adapted for decimals, and it works the same as for ints. The script is reported at the end of this message. Btw, talking about consistency: create table t(n int); insert into t values (1), (null); select distinct n from t; -- Result has two rows select count(distinct n) from t; -- 1 :) Thanks for the feedback! Life. -- Create a test table with data create table t1(a blob, b blob, c blob); insert into t1 values (dec(1), dec(0), dec(0)); insert into t1 values (dec(2), dec(0), dec(1)); insert into t1 values (dec(3), dec(1), dec(0)); insert into t1 values (dec(4), dec(1), dec(1)); insert into t1 values (dec(5), null, dec(0)); insert into t1 values (dec(6), null, dec(1)); insert into t1 values (dec(7), null, null); select decStr(a), decStr(b), decstr(c) from t1; -- Check to see what CASE does with NULLs in its test expressions select decStr(a), case when b<>dec(0) then 1 else 0 end from t1; select decStr(decAdd(a,10)), case when not b<>dec(0) then 1 else 0 end from t1; select decStr(decAdd(a,20)), case when b<>dec(0) and c<>dec(0) then 1 else 0 end from t1; select decStr(decAdd(a,30)), case when not (b<>dec(0) and c<>dec(0)) then 1 else 0 end from t1; select decStr(decAdd(a,40)), case when b<>dec(0) or c<>dec(0) then 1 else 0 end from t1; select decStr(decAdd(a,50)), case when not (b<>dec(0) or c<>dec(0)) then 1 else 0 end from t1; select decStr(decAdd(a,60)), case dec(b) when dec(c) then 1 else 0 end from t1; select decStr(decAdd(a,70)), case dec(c) when dec(b) then 1 else 0 end from t1; -- What happens when you multiple a NULL by zero? select decStr(decAdd(a,80)), decStr(decMul(b,0)) from t1; select decStr(decAdd(a,90)), decStr(decMul(b,c)) from t1; -- What happens to NULL for other operators? select decStr(decAdd(a,100)), decStr(decAdd(b,c)) from t1; -- Test the treatment of aggregate operators select count(*), count(dec(b)), decStr(decSum(b)), decStr(decAvg(b)), decStr(decMin(b)), decStr(decMax(b)) from t1; -- Check the behavior of NULLs in WHERE clauses select decStr(decAdd(a,110)) from t1 where b<dec(10); select decStr(decAdd(a,120)) from t1 where not b>dec(10); select decStr(decAdd(a,130)) from t1 where b<dec(10) OR c=dec(1); select decStr(decAdd(a,140)) from t1 where b<dec(10) AND c=dec(1); select decStr(decAdd(a,150)) from t1 where not (b<dec(10) AND c=dec(1)); select decStr(decAdd(a,160)) from t1 where not (c=dec(1) AND b<dec(10)); -- Check the behavior of NULLs in a DISTINCT query select distinct decStr(b) from t1; -- Check the behavior of NULLs in a UNION query select decStr(b) from t1 union select decStr(b) from t1; -- Create a new table with a unique column. Check to see if NULLs are considered -- to be distinct. create table t2(a blob, b blob unique); insert into t2 values(dec(1),dec(1)); insert into t2 values(dec(2),null); insert into t2 values(dec(3),null); select decStr(a), decStr(b) from t2; drop table t1; drop table t2; _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users