Вложенные запросы в проверочном операторе SQL - PullRequest
1 голос
/ 08 декабря 2010

Я пытаюсь добавить ограничение (в Oracle), которое ограничивает пользователя от создания записей, в которых «smth», «smth else» или «еще одна вещь» в поле уже существует. Вот как бы я это написал:

ALTER TABLE sometable
ADD CONSTRAINT sometable_text_chk
CHECK (
    caption IN ( 
        SELECT caption
        FROM sometable
        WHERE text NOT IN ('smth', 'smth else', 'one more thing')
    )
)

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

Ответы [ 4 ]

2 голосов
/ 08 декабря 2010

В основном вы пытаетесь провести какую-то общую проверку достоверности данных в одной таблице на основе данных в другой таблице (ПРИМЕЧАНИЕ: на самом деле, вероятно, нет, ожидая, пока ОП уточнит свой вопрос).

Обходной путь:

  • для общего случая - вы можете сделать довольно много внутри триггеров с точки зрения сложной проверки данных (включая остановку вашей базы данных даже для самых простых запросов на обновление, поэтому используйте с осторожностью)
  • в более конкретном случае вы пытаетесь выполнить некоторую динамическую проверку (более показательный пример был бы полезен) - вы можете динамически поддерживать ограничение CHECK с помощью «снимка» вашей проверки (это сводится к сохранению копия ссылочной таблицы внутри оператора проверки, так что это довольно уродливо)
  • возможно, вы можете проверить внешний ключ. это не то, как вы обычно проектируете базы данных, но если вы посмотрите на это семантически - вы утверждаете (с помощью CHECK), что есть связь между этой таблицей и каким-то другим объектом. хорошо, если эта сущность не реализована как отдельная таблица, может быть, так и должно быть? (такие проблемы иногда индикаторы плохого дизайна)
1 голос
/ 08 декабря 2010
ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (text not in ('smth', 'smth else', 'one more thing'))
/

С уважением, Роб.

0 голосов
/ 08 декабря 2010

Я признаю, что это может быть излишним.Если вы можете создать быстро обновляемое материализованное представление с обновлением при фиксации с определением, которое будет подсчитывать количество неверных значений в вашей таблице (возможно, что-то вроде ниже):

select count(*) as rows_with_errors
  from data_table   a
  join lookup_table b on(a.caption = b.caption);

Запрос долженвернуть счетчик нуля, потому что значения в data_table не могут содержать значения в lookup_table.Затем вы создаете проверочное ограничение для самого материализованного представления, CHECK (row_with_errors = 0).

Каждый раз, когда обновление или вставка фиксируется в data_table, материализованное представление обновляется.Но (и вот в чем дело), ​​если вы ввели значение в data_table, которое существует в lookup_table, count (*) вернет ненулевое значение, что приведет к сбою проверочного ограничения для материализованного представления, то есть всегооператор вставки / обновления завершится ошибкой / откатом.Voila!

0 голосов
/ 08 декабря 2010

Вы не можете добавить такое ограничение CHECK, вам нужно буквально предоставить полный список возможных значений:

CHECK (caption IN (Word1, Word2, Word3 ...))

Однако вы можете сделать по-другому:

CHECK (Caption <> 'smth' and caption <> 'smth else' and caption <> 'one more thing')

Но вы потеряли чеки от Sometable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...