Connect with Db2, Informix, Netezza, open source, and other data experts to gain value from your data, share insights, and solve problems.
Posted by: Serge RielauSome of you may know that I am engaged in enabling Oracle applications to DB2.One of the frequent "issues" we see are differences between the way how indexing works in Oracle and DB2 and, more specifically about different semantics for unique indexes. In DB2 a unique index requires that no two keys are the same.Sounds simple and clear on the surface, but not so clear when you consider NULLs.Generally speaking a NULL cannot be compared to a NULL and thus it is debatable whether one should allow more than one NULL key in a unique index. In the DB2 world only one NULL key may exist in a unique index.In Oracle however you can have multiple NULL keys.So does that mean in Oracle a NULL is not equal to a NULL? Not really.Let's look closer and define what a "key" is.A "key" is the set of columns making up an index. That is it may be one column or multiple columns.So when we talk about a NULL key that is a key where all columns are NULL.So when I say you can have multiple NULL keys in Oracle that means that a key will all NULLs can appear multiple times.But a key where at least one column is NOT NULL cannot appear multiple times.So this key is legal for a unique index in Oracle:
(NULL, NULL)(NULL, NULL)
(NULL, 1)(NULL, 1)
CREATE TABLE T(pk INT NOT NULL PRIMARY KEY, c1 VARCHAR(10));CREATE UNIQUE INDEX idx ON T(c1);
CREATE TABLE T(pk INT, c1 VARCHAR(10), idx INT GENERATED ALWAYS AS (CASE WHEN c1 IS NULL THEN pk ELSE NULL END));CREATE UNIQUE INDEX idx ON T(c1, idx);
CREATE TABLE T(pk INT NOT NULL PRIMARY KEY, c1 VARCHAR2(10), c2 DATE);CREATE UNIQUE INDEX idx ON T(c1, c2);
CREATE TABLE T(pk INT, c1 VARCHAR2(10), c2 DATE, idx INT GENERATED ALWAYS AS (CASE WHEN c1 IS NULL AND c2 IS NULL THEN pk ELSE NULL END));CREATE UNIQUE INDEX idx ON T(c1, c2, idx);
CREATE TABLE T(c1 VARCHAR2(10));CREATE UNIQUE INDEX idx ON T(c1);
CREATE TABLE T(c1 VARCHAR(10), pk INT NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY, idx INT GENERATED ALWAYS AS (CASE WHEN c1 IS NULL THEN pk ELSE NULL END));CREATE UNIQUE INDEX idx ON T(c1, idx);
db2 => insert into t(c1) values 1, 2, 3, 4, 5, NULL;DB20000I The SQL command completed successfully. db2 => insert into t(c1) values NULL;DB20000I The SQL command completed successfully. db2 => insert into t(c1) values 1;DB21034E The command was processed as an SQL statement because it was not avalid Command Line Processor command. During SQL processing it returned:SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key updatecaused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "2" constrains table "SERGE.T" from having duplicate values for the index key.SQLSTATE=23505 db2 => select * from t;C1 PK IDX---------- ----------- -----------1 1 -2 2 -3 3 -4 4 -5 5 -- 6 6- 7 7 7 record(s) selected.