Обсуждение: Can't use NULL in IN conditional?

Поиск
Список
Период
Сортировка

Can't use NULL in IN conditional?

От
pgsql-bugs@postgresql.org
Дата:
Charles Tassell (ctassell@isn.net) reports a bug with a severity of 3
The lower the number the more severe it is.

Short Description
Can't use NULL in IN conditional?

Long Description
I don't know if this is a "feature" that comes alogn with NULL values, or somethign I'm doing wrong, but I can't seem
tosearch for the NULL value via a WHERE xx IN clause.  I've re-written the query to use OR and it works fine then, but
notwith the IN clause.  This is with Postgres 7.02 on a Linux system (PostgreSQL 7.0.2 on i686-pc-linux-gnu, compiled
bygcc egcs-2.91.66) 


Sample Code
CREATE TABLE product_types (
  type_id serial,
  code  text
)
INSERT INTO product_types (code) VALUES ('0A');
INSERT INTO product_types (code) VALUES (NULL);
-- This works
SELECT type_id, code FROM product_types WHERE code = '0A' OR code = NULL;
-- This doesn't
SELECT type_id, code FROM product_types WHERE code IN ('OA', NULL);



No file was uploaded with this report

Re: Can't use NULL in IN conditional?

От
Tom Lane
Дата:
pgsql-bugs@postgresql.org writes:
> -- This works
> SELECT type_id, code FROM product_types WHERE code = '0A' OR code = NULL;
> -- This doesn't
> SELECT type_id, code FROM product_types WHERE code IN ('OA', NULL);

"code = NULL" is not legal SQL --- or at least, the standard's
interpretation of it is not what you appear to expect.  According to the
spec the result must always be NULL, which is effectively FALSE in this
context.

Since certain Microsoft products misinterpret "var = NULL" as "var IS NULL",
we've inserted a hack into our parser to convert a comparison against a
literal NULL to an IS NULL clause.  However, that only works for the
specific cases of "var = NULL" and "var <> NULL", not for any other
contexts where a null might be compared against something else.

Personally I regard this hack as a bad idea, and would prefer to take it
out.  I'd certainly resist extending it to the IN operator...

            regards, tom lane

Re: Can't use NULL in IN conditional?

От
"Robert B. Easter"
Дата:
On Monday 11 December 2000 10:51, Tom Lane wrote:
> pgsql-bugs@postgresql.org writes:
> > -- This works
> > SELECT type_id, code FROM product_types WHERE code = '0A' OR code = NULL;
> > -- This doesn't
> > SELECT type_id, code FROM product_types WHERE code IN ('OA', NULL);
>
> "code = NULL" is not legal SQL --- or at least, the standard's
> interpretation of it is not what you appear to expect.  According to the
> spec the result must always be NULL, which is effectively FALSE in this
> context.
>
> Since certain Microsoft products misinterpret "var = NULL" as "var IS
> NULL", we've inserted a hack into our parser to convert a comparison
> against a literal NULL to an IS NULL clause.  However, that only works for
> the specific cases of "var = NULL" and "var <> NULL", not for any other
> contexts where a null might be compared against something else.
>
> Personally I regard this hack as a bad idea, and would prefer to take it
> out.  I'd certainly resist extending it to the IN operator...
>
>             regards, tom lane

What you are saying agrees with things I've read elsewhere, and a little
definition/note that I wrote on my "Databasing" Terms page:

three-valued logic:
    a logic system that employs TRUE, FALSE, and UNKNOWN. NULL values introduce
UNKNOWN into boolean operations. A truth table must be used to lookup the
proper value (TRUE or FALSE) of UNKNOWN under specific operations. In SQL
implementations that use three-valued logic, you must consult the
documentation for its truth table. Some newer implementations of SQL
eliminate UNKNOWN, and may generally behave as follows: all boolean tests
involving NULL return FALSE except the explicit test IS NULL, e.g., if NULL
is a possibility, it has to be tested for explicity using IS NULL or IS NOT
NULL.  (any additions/corrections to this definition/note will be happily
considered)

I think Bruce Momjian's book says this too:
http://www.postgresql.org/docs/aw_pgsql_book/node45.html
(that book is really useful!)

--
-------- Robert B. Easter  reaster@comptechnews.com ---------
- CompTechNews Message Board   http://www.comptechnews.com/ -
- CompTechServ Tech Services   http://www.comptechserv.com/ -
---------- http://www.comptechnews.com/~reaster/ ------------

RE: Can't use NULL in IN conditional?

От
Piers Scannell
Дата:
Since it's probably a "special case" I'd feel it good software engineering
practice to make that fact explicit anyway.

For example:

  SELECT type_id, code FROM product_types WHERE code IN ('0A', 'F3', '99')
OR code IS NULL;

I don't know how that would affect the speed but it might be the clearest
expression of intent.


Piers Scannell
Systems Engineer, GlobeCast France Telecom
Tel: +44 1707 667 228   Fax: +44 1707 667 206



> -----Original Message-----
> From: pgsql-bugs@postgresql.org [mailto:pgsql-bugs@postgresql.org]
> Sent: 11 December 2000 07:49
> To: pgsql-bugs@postgresql.org
> Subject: [BUGS] Can't use NULL in IN conditional?
>
>
> Charles Tassell (ctassell@isn.net) reports a bug with a severity of 3
> The lower the number the more severe it is.
>
> Short Description
> Can't use NULL in IN conditional?
>
> Long Description
> I don't know if this is a "feature" that comes alogn with
> NULL values, or somethign I'm doing wrong, but I can't seem
> to search for the NULL value via a WHERE xx IN clause.  I've
> re-written the query to use OR and it works fine then, but
> not with the IN clause.  This is with Postgres 7.02 on a
> Linux system (PostgreSQL 7.0.2 on i686-pc-linux-gnu, compiled
> by gcc egcs-2.91.66)
>
>
> Sample Code
> CREATE TABLE product_types (
>   type_id serial,
>   code  text
> )
> INSERT INTO product_types (code) VALUES ('0A');
> INSERT INTO product_types (code) VALUES (NULL);
> -- This works
> SELECT type_id, code FROM product_types WHERE code = '0A' OR
> code = NULL;
> -- This doesn't
> SELECT type_id, code FROM product_types WHERE code IN ('OA', NULL);
>
>
>
> No file was uploaded with this report
>

Re: Can't use NULL in IN conditional?

От
Tom Lane
Дата:
"Robert B. Easter" <reaster@comptechnews.com> writes:
> What you are saying agrees with things I've read elsewhere, and a little
> definition/note that I wrote on my "Databasing" Terms page:

> three-valued logic:
> a logic system that employs TRUE, FALSE, and UNKNOWN. NULL values introduce
> UNKNOWN into boolean operations. A truth table must be used to lookup the
> proper value (TRUE or FALSE) of UNKNOWN under specific operations. In SQL
> implementations that use three-valued logic, you must consult the
> documentation for its truth table.

Three-valued logic is perfectly straightforward if you keep in mind the
interpretation of NULL/UNKNOWN: "I don't know if this is true or false".
Thus:

    NOT unknown => unknown

    false AND unknown => false   (it can't possibly be true)
    true AND unknown => unknown
    unknown AND unknown => unknown

    false OR unknown => unknown
    true OR unknown => true   (it's true no matter what the unknown is)
    unknown OR unknown => unknown

For ordinary operators such as "=", the result is generally NULL if any
input is NULL, although there are some specific cases where you can
deduce a correct result knowing only some of the inputs.  In particular,
NULL = NULL does not yield TRUE, it yields UNKNOWN.  This is correct
when you consider that NULL is not a specific value, but a placeholder
for an unknown value.  (Reference: SQL99 section 8.2 general rule 1a.)

IS NULL and IS NOT NULL are not ordinary operators in this sense, since
they can deliver a non-null result for NULL input.

Also, SQL specifies that a WHERE clause that evaluates to "unknown" is
taken as false, ie, the row is not selected.

Bottom line is that in a spec-conformant implementation,
    WHERE code = '0A' OR code = NULL
will act the same as if you'd just written "WHERE code = '0A'"; the
second clause always yields unknown and so can never cause the WHERE to
be taken as true.

> Some newer implementations of SQL
> eliminate UNKNOWN, and may generally behave as follows: all boolean tests
> involving NULL return FALSE except the explicit test IS NULL, e.g., if NULL
> is a possibility, it has to be tested for explicity using IS NULL or IS NOT
> NULL.

They may *appear* to return FALSE if you aren't looking too closely,
since WHERE treats top-level results of FALSE and UNKNOWN the same.
If they really don't make the distinction then they are broken.
AFAICT, neither SQL92 nor SQL99 regard NULL support as optional.

            regards, tom lane

Re: Can't use NULL in IN conditional?

От
"Robert B. Easter"
Дата:
On Monday 11 December 2000 12:34, Tom Lane wrote:
> Three-valued logic is perfectly straightforward if you keep in mind the
> interpretation of NULL/UNKNOWN: "I don't know if this is true or false".
> Thus:
>
>     NOT unknown => unknown
>
>     false AND unknown => false   (it can't possibly be true)
>     true AND unknown => unknown
>     unknown AND unknown => unknown
>
>     false OR unknown => unknown
>     true OR unknown => true   (it's true no matter what the unknown is)
>     unknown OR unknown => unknown
>
> For ordinary operators such as "=", the result is generally NULL if any
> input is NULL, although there are some specific cases where you can
> deduce a correct result knowing only some of the inputs.  In particular,
> NULL = NULL does not yield TRUE, it yields UNKNOWN.  This is correct
> when you consider that NULL is not a specific value, but a placeholder
> for an unknown value.  (Reference: SQL99 section 8.2 general rule 1a.)
>
> IS NULL and IS NOT NULL are not ordinary operators in this sense, since
> they can deliver a non-null result for NULL input.
>
> Also, SQL specifies that a WHERE clause that evaluates to "unknown" is
> taken as false, ie, the row is not selected.
>
> Bottom line is that in a spec-conformant implementation,
>     WHERE code = '0A' OR code = NULL
> will act the same as if you'd just written "WHERE code = '0A'"; the
> second clause always yields unknown and so can never cause the WHERE to
> be taken as true.
>
> > Some newer implementations of SQL
> > eliminate UNKNOWN, and may generally behave as follows: all boolean tests
> > involving NULL return FALSE except the explicit test IS NULL, e.g., if
> > NULL is a possibility, it has to be tested for explicity using IS NULL or
> > IS NOT NULL.
>
> They may *appear* to return FALSE if you aren't looking too closely,
> since WHERE treats top-level results of FALSE and UNKNOWN the same.
> If they really don't make the distinction then they are broken.
> AFAICT, neither SQL92 nor SQL99 regard NULL support as optional.
>
>             regards, tom lane

Thanks for the clarification and SQL reference.  I spent some time on this
today and updated a file of mine at

http://www.comptechnews.com/~reaster/dbdesign.html#three-valued-logic

to take into consideration these things.  If you do take a look at it and
find an error, I will fix it.  This dbdesign.html file is a file linked to
from http://postgresql.readysetnet.com/docs/faq-english.html so I'm hoping to
keep it correct and useful.  Thanks :)


--
-------- Robert B. Easter  reaster@comptechnews.com ---------
- CompTechNews Message Board   http://www.comptechnews.com/ -
- CompTechServ Tech Services   http://www.comptechserv.com/ -
---------- http://www.comptechnews.com/~reaster/ ------------