Как создать уникальный индекс для полей с возможными значениями null (Oracle 11g)?

вот пример таблицы с 3 столбцами (ID, UNIQUE_VALUE, UNIQUE_GROUP_ID)

Я хочу ниже записи могут быть разрешены:

(1, NULL, NULL)
(2, NULL, NULL)

или

(3, NULL, 7)
(4, 123, 7)

или (Примечание: это условие не допускаются в unique index, ни unique constraint)

(5, NULL, 7)
(6, NULL, 7)

и это не может быть разрешено:

(7, 123, 7)
(8, 123, 7)

Я создал уникальный индекс для последних 2 столбцов, но только первые 2 примера могут быть разрешены.

можно ли позволить db проверяем уникальность этих 2 столбцов только тогда, когда оба не равны нулю?

2 ответов


вы хотите только обеспечить уникальность строк, где оба UNIQUE_VALUE и UNIQUE_GROUP_ID не являются null. Для этого можно использовать уникальный функциональный индекс:

CREATE UNIQUE INDEX func_based_index ON the_table
  (CASE WHEN unique_value IS NOT NULL
         AND unique_group_id IS NOT NULL
        THEN UNIQUE_VALUE || ',' || UNIQUE_GROUP_ID
   END);

вы можете использовать функцию nvl, чтобы избежать нулей и вместо этого поместить другое значение,

create unique index func_idx on TEST_TABLE (nvl(UNIQUE_VALUE,1), UNIQUE_GROUP_ID);

недостатком является то, что ваш индекс будет больше, и если вы хотите искать значения null, вам придется использовать функцию nvl, чтобы избежать table_access_full.

также все значения null будут расположены под одной ветвью индекса, поэтому убедитесь, что ваши гистограммы обновлены.

надеюсь, это вам поможет:)