Как ограничить таблицу базы данных, чтобы только одна строка могла иметь определенное значение в столбце?

Используя Oracle, если значение столбца может быть "ДА" или "НЕТ", возможно ли ограничить таблицу так, чтобы только одна строка могла иметь значение "ДА"?

Я бы предпочел изменить структуру таблицы, но это невозможно.

[UDPATE] К сожалению, нулевые значения не допускаются в этой таблице.

7 ответов

Решение

Используйте индекс на основе функций:

create unique index only_one_yes on mytable
(case when col='YES' then 'YES' end);

Oracle индексирует только те ключи, которые не являются полностью нулевыми, и выражение CASE здесь гарантирует, что все значения 'NO' будут заменены на нули и, следовательно, не проиндексированы.

Это хакерский хак, но если столбец допускает NULL, то вы можете использовать NULL вместо "NO" и "YES", как и раньше. Примените ограничение уникального ключа к этому столбцу, и вы никогда не получите два значения "ДА", но все равно будете иметь много НЕТ.

Обновление: @Nick Pierpoint: предложено добавить проверочное ограничение, чтобы значения столбцов ограничивались только "YES" и NULL. Синтаксис все проработан в его ответе.

Вы захотите проверить статью Тома Кайта с именно этим вопросом и его ответом:

http://tkyte.blogspot.com/2008/05/another-of-day.html

Резюме: не используйте триггеры, не используйте автономные транзакции, используйте две таблицы.

Если вы используете базу данных Oracle, вы ДОЛЖНЫ познакомиться с AskTom и получить его книги.

Это не работает с определением таблицы.

Однако, если вы обновите таблицу с помощью триггера, вызывающего хранимую процедуру, вы можете убедиться, что только одна строка содержит "YES".

  1. Установите все строки в "НЕТ"
  2. Установите строку, которую вы хотите, чтобы ДА

Исходя из моего комментария к предыдущему ответу yukondude, я бы добавил уникальный индекс и проверочное ограничение:

create table mytest (
    yesorno varchar2(3 char)
);

create unique index uk_mytest_yesorno on mytest(yesorno);

alter table mytest add constraint ck_mytest_yesorno check (yesorno is null or yesorno = 'YES');

Поддерживает ли Oracle что-то вроде отфильтрованных индексов (на прошлой неделе я слышал, что, например, MSSQL2008 поддерживает)? Возможно, вы можете определить уникальный ключ, который применяется только к строкам со значением "Да" в вашем столбце.

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

Другие вопросы по тегам