Live data from Hacker News

SQL nulls are weird

jirevwe.github.io

231–240 of 293 posts

Re: SQL nulls are weird

#231

Earlier quoted context omitted.

This is confusing when you know that NULLs are not comparable, but it makes some sense if you consider the result of distinct/union as the output of a GROUP BY. You can consider everything that's NULL to be part of the same group, all the values are unknown. So NULLs are not comparable but they are part of the same set.

If nulls are distinct then group by should not group them together, this just ignores the problem. Why does group by treat them as equal?

Nulls are not necessarily distinct.

I believe this confusion is confusing the tool with the thing being measured. For simplicity, I will use the analogy of a record (stored as a row in the database) as an observation in a scientific experiment. If the tool was able to record a value, I enter a value like 579.13. If the tool was not able to record a value, the tool will enter NULL. I make a total of one hundred observations. Of one hundred rows, some have values and some are NULL.

Are NULLs distinct values? No, they are simply a failure in measurement; it is like asking if all errors are distinct or the same. Are NULLS part of the same dataset? Yes, because they are all observations for the same scientific experiment. What does it mean when "select distinct ... " returns several rows for known/measurable values and but only one row for NULL? If this is confusing, the scientist can update the rows and substitute "UNKNOWN/ERROR" for every NULL. When you do "select distinct ...", you will get the same thing. It will return several rows for known/measurable values and but only one row for "UNKNOWN/ERROR".

Re: SQL nulls are weird

#232
post #203

Earlier quoted context omitted.

Yeah the 3 valued logic of SQL trips people up, me too from time to time

SQL is not three valued. Neither is NULL . BOOLEAN is accused of being three-valued but it has two values and like all values they can be unknown. Similarly a SMALLINT has 65,536 possible values not 65,537.

It’s not? https://modern-sql.com/concept/three-valued-logic

Re: SQL nulls are weird

#233
post #203

Earlier quoted context omitted.

SQL is not three valued. Neither is NULL . BOOLEAN is accused of being three-valued but it has two values and like all values they can be unknown. Similarly a SMALLINT has 65,536 possible values not 65,537.

It’s not? https://modern-sql.com/concept/three-valued-logic

It’s not.

Your link makes the same mistake I already addressed. It conflates nullable booleans with tri-state logic.

Null is not a value. It is the absence of a value.

> The SQL null value basically means “could be anything”.

This is wrong. Null means it could be any valid value but that value is unknown. If the datatype is DATE then the value cannot be boolean TRUE or the string ‘purple’.

Re: SQL nulls are weird

#234
post #152

Earlier quoted context omitted.

Well, that's a problem on many of the devices I've seen: zero is a valid memory address and dereferencing it does not cause any kind of crash. In fact some hardware requires reading or maybe even writing to that address. In an age of virtual memory there's no reason why zero should cause a crash and it wastes an entire page of memory for every application to make that happen, if it does.

I haven't had the chance to work on any MMU-less devices, but I don't quite follow your remark about wasting a page. Crashing is just the default behaviour in the absence of a mapping and consumes no resources.

The granularity of virtual address mapping is usually a page. On many systems, that's 4 kilobytes of address space. In order to trigger a fault when the address 0x0000000000000000 is dereferenced, it's necessary to map the entire address range from 0x0000000000000000 to 0x0000000000000fff to the same faulting behaviour.

That's a waste of a page.

Re: SQL nulls are weird

#235

Earlier quoted context omitted.

What happens if your data is produced by some automated process such as a sensor reading and occasionally the sensor fails to return a value? NULL seems exactly the appropriate value to use.

Then you're supposed to use another table with a foreign key to canonical measurement record. This is the concept of fully normalized schemas. What you're describing is closer to how people do it in practice.

I'm still a bit confused. Suppose you have another table, call it temperatures with columns id and temperature, where every row contains only a valid temperature (no NULL records), and you have a main logging table with date and temperature_id so that you can join on temperature_id = temperatures.id. This seems to be what you mean, with a canonical measurement record table related via the temperature_id foreign key.

But then if your sensor fails to record a measurement don't you end up with NULL for that row's temperature_id?

Re: SQL nulls are weird

#236
post #234

Earlier quoted context omitted.

I haven't had the chance to work on any MMU-less devices, but I don't quite follow your remark about wasting a page. Crashing is just the default behaviour in the absence of a mapping and consumes no resources.

The granularity of virtual address mapping is usually a page. On many systems, that's 4 kilobytes of address space. In order to trigger a fault when the address 0x0000000000000000 is dereferenced, it's necessary to map the entire address range from 0x0000000000000000 to 0x0000000000000fff to the same faulting behaviour. That's a waste of a page.

Yeah but there is no "page" there. Assuming a process starts with an empty page table (meaning every single address will segfault), you don't have to do anything else to get the crashing behaviour for null.

Unless you're talking about some kind of device which supports virtual memory, but also by default sets up mappings, including at 0 which seems weird to me.

Re: SQL nulls are weird

#237
post #188

SQL NULLs aren't weird , they're just based off of Kleene's TRUE-FALSE-UNKNOWN logic! If you want you can read NULL as UNKNOWN and suddenly a whole bunch of operations involving them become a lot more intuitive: 1. TRUE OR UNKNOWN = TRUE, because you know you have at least one TRUE already. 2. TRUE AND UNKNOWN = UNKNOWN, because you don't know whether you have two TRUEs or not. It's just out there. 3. UNKNOWN XOR UNK…

> SQL NULLs aren't weird, they're just based off of Kleene's TRUE-FALSE-UNKNOWN logic! Kleene's TRUE-FALSE-UNKNOWN logic is weird. SQL nulls effectively violate the reflexive property of equality, because X=X does not result in a value of TRUE. And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause. So that means that X=X is effectively FALSE in SQL*. That is a clown langua…

> And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause.

I don't think any databases treat `NULL` as `FALSE` in the WHERE clause. `SELECT * FROM foo WHERE bar = NULL` doesn't return rows with a NULL in the bar column. `SELECT * FROM foo WHERE bar != NULL` doesn't return rows without NULL in the bar column. `SELECT * FROM foo WHERE (bar = 'a') = NULL;` doesn't return rows where bar is not equal to `a`[1]. As far as I know every DB treats NULL as what it is, an unknown value.

It also doesn't to my mind violate the reflexive property because NULL is not equal to anything. It is a marker for an unknown value, not a value in and of itself. If you have a database of every person in a room and what color shirt they're wearing, and in your database, Alice and Bob both have NULL in their "shirt_color" column, that does not mean that Alice and Bob have the same color shirt. Nor does it mean that they don't have the same color shirt. Nor does it mean that someone with a green colored shirt has the same color shirt as Bob or Alice. It doesn't mean they don't have a shirt either. It means you don't have a record of/don't know what color their shirts are. You can't violate the reflexive property because you can't say what color shirt they have. You're not doing `X = X -> false`, you're doing `X = UNKNOWN -> UNKNOWN`

[1]: https://www.db-fiddle.com/f/iVDDRJos1pUqxnuy1jTEEe/0

Re: SQL nulls are weird

#238
post #29

Earlier quoted context omitted.

SQL NULL doesn’t behave like “unknown” in all contexts. That’s one issue of NULL, that it doesn’t really have consistent semantics.

Furthermore if null only means unknown then we need a value for “known absent”, there’s a reason why null is so often used as that.

But the "known absent" value is going to be different for different domains. For example, in EEOC databases the "known absent" value for a race would be "declined to answer". In a database of test scores, it might be "Didn't complete", but it could also be "was absent from class on exam day" so SQL can't specify what that is. On the other hand "this value is unknown" can use the same marker in all domains, and SQL chose NULL as that marker. To be completely strict about it, "have a value/don't have a value" is one piece of data if that's something you care about and "what is that value" is another one. So in an ideal system, you should have a column for "value is [present | known absent | unknown]" and a separate column for the actual value when "value is present"

Most of the time it's not that important and people can and do shortcut "null" to mean "not present" but then the issues with using null in equality statements is a result of taking the short cut, not necessarily with the logic around null.

Re: SQL nulls are weird

#239
post #188

Earlier quoted context omitted.

> SQL NULLs aren't weird, they're just based off of Kleene's TRUE-FALSE-UNKNOWN logic! Kleene's TRUE-FALSE-UNKNOWN logic is weird. SQL nulls effectively violate the reflexive property of equality, because X=X does not result in a value of TRUE. And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause. So that means that X=X is effectively FALSE in SQL*. That is a clown langua…

> And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause. I don't think any databases treat `NULL` as `FALSE` in the WHERE clause. `SELECT * FROM foo WHERE bar = NULL` doesn't return rows with a NULL in the bar column. `SELECT * FROM foo WHERE bar != NULL` doesn't return rows without NULL in the bar column. `SELECT * FROM foo WHERE (bar = 'a') = NULL;` doesn't return rows w…

It treats the NULL/unknown value of the boolean as false

1 NULL => Boolean UNKNOWN,

so SELECT * FROM foo WHERE 1 NULL returns nothing.

1 = NULL => Boolean UNKNOWN,

so SELECT * FROM foo WHERE 1 = NULL returns nothing.

That's the thing that's being treated as FALSE. That UNKNOWN. Not the value of NULL itself.

> You're not doing `X = X -> false`, you're doing `X = UNKNOWN -> UNKNOWN`

That's not how "=" works. If you want a relationship for testing equality than handles unknown, don't call it equality.

Basic properties of equality, from Wikipedia

https://en.wikipedia.org/wiki/Equality_(mathematics)

- Reflexivity: for every a, one has a = a.

- Symmetry: for every a and b, if a = b, then b = a.

- Transitivity: for every a, b, and c, if a = b and b = c, then a = c.

edit:

We can also see the incoherence of this concept when we look at set theory.

Because UNKONWN booleans are neither true or false, if you use them in a WHERE clause you get the ugly result that the set of

    X ⋃ Xᶜ
is not everything.

Re: SQL nulls are weird

#240
post #188

SQL NULLs aren't weird , they're just based off of Kleene's TRUE-FALSE-UNKNOWN logic! If you want you can read NULL as UNKNOWN and suddenly a whole bunch of operations involving them become a lot more intuitive: 1. TRUE OR UNKNOWN = TRUE, because you know you have at least one TRUE already. 2. TRUE AND UNKNOWN = UNKNOWN, because you don't know whether you have two TRUEs or not. It's just out there. 3. UNKNOWN XOR UNK…

> SQL NULLs aren't weird, they're just based off of Kleene's TRUE-FALSE-UNKNOWN logic! Kleene's TRUE-FALSE-UNKNOWN logic is weird. SQL nulls effectively violate the reflexive property of equality, because X=X does not result in a value of TRUE. And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause. So that means that X=X is effectively FALSE in SQL*. That is a clown langua…

> And in many contexts in SQL, NULL is treated as equivalent to false, such as within a WHERE clause.

NULL is not equivalent to FALSE, it is neither FALSE nor TRUE. It has the same effect as FALSE as the final result of evaluating a WHERE clause condition only because WHERE clause conditions allow a row to be included only when they evaluate strictly to TRUE. But if NULL were equivalent to FALSE in a WHERE clause, than a WHERE clause condition which would evaluate to NULL that was instead negated would be equivalent to TRUE but instead it remains NULL which remains not TRUE.

Post reply on HN