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

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

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

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

О боже, нули не разрешены - это немного меняет ситуацию - теперь вам нужно использовать индекс на основе функций (@Tony Andrews). По-прежнему избегайте триггеров и автономных транзакций.

Nick Pierpoint 10.10.2008 00:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
16
1
7 873
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

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

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

-1 для решения на основе триггера. Они никогда не работают для обеспечения ограничений на уровне таблицы.

David Aldridge 08.10.2008 18:32

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

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

Ничего лишнего - это правильный путь. +1

Nick Pierpoint 08.10.2008 16:17

Вам также нужно будет добавить в таблицу ограничение проверки, чтобы она не разрешала ничего, кроме «YES» или null.

Nick Pierpoint 08.10.2008 16:21

если вы хотите, чтобы он выглядел красиво, вы, вероятно, также могли бы обернуть представление NVL вокруг него, тогда вы получите свой Y / N

Matthew Watson 08.10.2008 17:13

Ну, использовать NULL сложно, если вы хотите присоединиться к нему. Возможно, это стоит сделать, но это все же компромисс в дизайне от более правильного подхода.

David Aldridge 08.10.2008 18:27

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

Никаких фильтрованных индексов, но ФБР предлагают более гибкий (хотя, возможно, менее сжатый) способ сделать то же самое.

orbfish 25.10.2011 20:27
Ответ принят как подходящий

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

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

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

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

трудно поддерживать в стабильной среде

David Aldridge 08.10.2008 18:34

Следуя моему комментарию к предыдущему ответу 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');

Я думаю, что до тех пор, пока NULL подходит в качестве значения «не да», этот метод имеет преимущество перед методом FBI, потому что ограничения могут, по крайней мере, использоваться оптимизатором. Я думаю, что запросы с предикатами yesorno = 'YES' и yesorno is null будут получать более точные оценки мощности.

David Aldridge 08.10.2008 17:36

Поскольку всегда будет только одна строка с «YES» и каждая другая строка с нулевым значением, тогда вы получите индекс, используемый для поиска строки «YES», и полное сканирование (совершенно справедливо), чтобы получить все остальное ( "НЕТ").

Nick Pierpoint 08.10.2008 18:10

Конечно - вопрос лишь в том, является ли замена «Нет» на Null стоящим компромиссом для достижения этой цели.

David Aldridge 08.10.2008 18:33

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

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

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

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

Заданный вопрос немного отличается от этого, в вопросе Тома в таблице может быть несколько «Y», но только по одному на страну. Как я читал, в этом примере в таблице может быть только 1 Да, и в этом случае индексное решение, похоже, работает. Но да, AskTom необходим для базы данных Oracle.

Matthew Watson 09.10.2008 10:42

Я согласен. Если бы Тому задали этот вопрос, я бы предположил, что он определенно выбрал бы индексное решение.

Nick Pierpoint 09.10.2008 23:56

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