SQLite Forum

feature request: Add option to UNIQUE constrain to treat NULLs as distinct
Login

feature request: Add option to UNIQUE constrain to treat NULLs as distinct

(1) By anonymous on 2020-03-28 21:54:37 [link] [source]

Hi,

I did read https://www.sqlite.org/nulls.html and few other posts on mailing list, so I understand the curent status, and compatibility, as well the standard ambiguity.

I would like UNIQUE constraint to have option to treat NULLs on all involved columns / expressions, or some columns as distinct.

https://www.sqlite.org/nulls.html suggests to recompile sqlite with a modified macro, but that is not always possible, and would also apply to all unique constraints.

I have this DDT:

CREATE TABLE IF NOT EXISTS data (
  date text,
  time text,
  abbreviation_canton_and_fl text,
  ncumul_tested integer,
  ncumul_conf integer,
  ncumul_hosp integer,
  ncumul_ICU integer,
  ncumul_vent integer,
  ncumul_released integer,
  ncumul_deceased integer,
  source text,
  UNIQUE(date, time, abbreviation_canton_and_fl)
)

time can be NULL, however, I don't want to have two same entries if (date=X, time=NULL, abbreviation_canton_and_fl=CC).

I use INSERT OR REPLACE for inserting data.

The issue is that because time can be NULL, and 'source' column is almost always unique (it contains some timestamps), I can't use SELECT DISTINCT * FROM data; either, because DISTINCT operates on all columns, not just date, time, abbreviation_canton_and_fl.

So, my proposal would be to have something like this:

CREATE TABLE IF NOT EXISTS data (
  date text NOT NULL,
  time text,
  abbreviation_canton_and_fl text NOT NULL,
  ncumul_tested integer,
  ncumul_conf integer,
  ncumul_hosp integer,
  ncumul_ICU integer,
  ncumul_vent integer,
  ncumul_released integer,
  ncumul_deceased integer,
  source text,
  UNIQUE(date, time NULL_ALWAYS_DISTINCT, abbreviation_canton_and_fl)
)

WDYT?

(2) By Keith Medcalf (kmedcalf) on 2020-03-28 23:38:22 in reply to 1 [link] [source]

Why not simply declare a default value?

CREATE TABLE IF NOT EXISTS data (
  date text NOT NULL,
  time text default 'N/A',
  abbreviation_canton_and_fl text NOT NULL,
  ncumul_tested integer,
  ncumul_conf integer,
  ncumul_hosp integer,
  ncumul_ICU integer,
  ncumul_vent integer,
  ncumul_released integer,
  ncumul_deceased integer,
  source text,
  UNIQUE(date, time, abbreviation_canton_and_fl)
);

Nulls are not a value. NULL means "any possible value within the domain, but I don't know which value" and therefore they are indistinct by very definition. If you want a value, put a value. If you want the default value to be something rather than unknown/missing (ie, NULL) then why cannot you do that?

(3) By Richard Hipp (drh) on 2020-03-29 00:00:55 in reply to 1 [source]

CREATE UNIQUE INDEX data_x1 ON data(date, coalesce(time,''), abbreviation_canton_and_fl);

(4) By anonymous on 2020-03-30 21:12:40 in reply to 3 [link] [source]

That is a nice and obvious trick, and it works. Thank you!