To be honest I'm a bit confused about the wording of these two bullets
too. But here're my comments and clarifications:

>>     Perhaps you are referring to the following statement from SQL92:
>>
>>         A unique constraint is satisfied if and only if no two rows in
>>         a table have the same non-null values in the unique columns.
>>
> IMHO: as they did't just write  ".. have the same values in the unique
> columns", the database should only compare those columns that are
> non-null when enforcing uniqueness. (just as above -- and as SQlite does
> it).

Be careful, everything depends here on the meaning of "the same
values". From the human POV all NULLs are the same (probably with the
differentiation per datatype). From the SQL point of view comparison
NULL = NULL is always false, so every NULL is unique and is not the
same as any other NULL (although comparison NULL != NULL is always
false too).
And probably author of this FAQ meant to say exactly this: you can
treat uniqueness and term "same values" as humans do (and as MS SQL
does) or as SQL does (and as SQLite does). For me wording of the
standard is pretty clearly means to treat NULLs as SQLite does it. I
can't even imagine how someone can understand it in another way.

And here're tests showing this issue:

SQLite version 3.6.14.2
sqlite> create table t (a int, b int, unique (a,b));
sqlite> insert into t values (1,2);
sqlite> insert into t values (1,2);
SQL error: columns a, b are not unique
sqlite> insert into t values (1,null);
sqlite> insert into t values (1,null);
sqlite> insert into t values (null,null);
sqlite> insert into t values (null,null);
sqlite> select * from t;
1|2
1|
1|
|
|
sqlite>

sqsh-2.1.4 Copyright (C) 1995-2001 Scott C. Gray
Portions Copyright (C) 2004-2006 Michael Peppler
1> create table #t (a int, b int, unique (a,b))
2> go
1> insert into #t values (1,2)
2> go
(1 row affected)
1> insert into #t values (1,2)
2> go
Violation of UNIQUE KEY constraint 'UQ__#t________________42ACE4D4'.
Cannot insert duplicate key in object 'dbo.#t'.
The statement has been terminated.
1> insert into #t values (1,null)
2> go
(1 row affected)
1> insert into #t values (1,null)
2> go
Violation of UNIQUE KEY constraint 'UQ__#t________________42ACE4D4'.
Cannot insert duplicate key in object 'dbo.#t'.
The statement has been terminated.
1> insert into #t values (null,null)
2> go
(1 row affected)
1> insert into #t values (null,null)
2> go
Violation of UNIQUE KEY constraint 'UQ__#t________________42ACE4D4'.
Cannot insert duplicate key in object 'dbo.#t'.
The statement has been terminated.
1> select * from #t
2> go
 a           b
 ----------- -----------
        NULL        NULL
           1        NULL
           1           2

(3 rows affected)
1>


Pavel

On Wed, Dec 30, 2009 at 9:13 AM, Tobias Hoffmann
<lsqlite-l...@thax.hardliners.org> wrote:
> Hi,
>
> I had a hard time to understand the FAQ entry on UNIQUE constraint -- in
> the end I had to try out sqlite's behavior myself because the FAQ  -- so
> maybe the wording can be improved and/or an example added.
>
> Here a some comments:
>> *(26) The SQL standard requires that a UNIQUE constraint be enforced
>> even of one or more of the columns in the constraint are NULL, but
>> SQLite does not do this. Isn't that a bug?*
> So this seems to imply that two NULL values will not violate the
> UNIQUEness of two rows in SQlite. [Btw. shouldn't it be "... enforced
> even IF one or ..."?]
>>
>>     Perhaps you are referring to the following statement from SQL92:
>>
>>         A unique constraint is satisfied if and only if no two rows in
>>         a table have the same non-null values in the unique columns.
>>
> IMHO: as they did't just write  ".. have the same values in the unique
> columns", the database should only compare those columns that are
> non-null when enforcing uniqueness. (just as above -- and as SQlite does
> it).
>>
>>     That statement is ambiguous, having at least two possible
>>     interpretations:
>>
> Now the confusion begins.
>>
>>        1. A unique constraint is satisfied if and only if no two rows
>>           in a table have the same values and have non-null values in
>>           the unique columns.
>>
> Shall this mean something like (parenthesis to show parsing precendence)
>  (no two rows in the table have the same values) and ([they] have
> non-null values) ...    [after some time I realized: this does not make
> much sense. But how else was it meant?]
> or
>  no two rows in a table have (the same values and have non-null values)
> in the unique columns.    [maybe removing the second "have" would help]
>>
>>        2. A unique constraint is satisfied if and only if no two rows
>>           in a table have the same values in the subset of unique
>>           columns that are not null.
>>
> So you compare only those columns that are not NULL, right?
> Where is the difference to (1)? [this made understanding (1) even more
> difficult to me].
> And why does the following paragraph state that that SQLite does not
> follow this interpretation, although it seems that this is the
> unexpected behavior in the original question?
>>
>>     SQLite follows interpretation (1), as does PostgreSQL, MySQL,
>>     Oracle, and Firebird. It is true that Informix and Microsoft SQL
>>     Server use interpretation (2), however we the SQLite developers
>>     hold that interpretation (1) is the most natural reading of the
>>     requirement and we also want to maximize compatibility with other
>>     SQL database engines, and most other database engines also go with
>>     (1), so that is what SQLite does.
>>
> After all I tried with SQLite and found out that you can have two rows
> with NULL in the same (unique-constraint) column.
> But I'm not sure if this is really the point of the question, as I still
> haven't understood (2) [and don't have MSSQL to test] - or whether its
> [wild guess:] about certain behavior with multi-column indices.
>
> If this is clear to everybody except me, I would appreciate a hint...
> otherwise please consider clarifying this FAQ.
>
>  Tobias
>
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to