Есть ли способ дать удобное сообщение об ошибке при нарушении ограничения - PullRequest
12 голосов
/ 20 мая 2011

Скажем, у меня есть столбец Gender и ограничение CHECK( Gender IN ('F', 'M', 'OTHER')).
Если я случайно забуду обработать это на стороне клиента, пользователь увидит что-то вроде
ORA-02290: check constraint (SYS_C099871244) violated
что не очень полезно ни для пользователя, ни для разработчика, который поддерживает или отлаживает

Есть ли способ предоставления сообщения, определенного разработчиком, например (псевдо) Java
assert Gender IN (0,1):'Gender must be F or M'

Единственный способ, о котором я могу думать, - это перенести ограничения на триггер BEFORE UPDATE OR INSERT, а в случае сбоя выполнить Raise_Application_Error( code, my_message ). Но мне это не нравится

EDIT Список конкретных причин согласно комментариям
1. Мне действительно нравится держать логику как можно ближе к данным
2. Для конечного пользователя сообщение Raise_Application_Error неотличимо от сообщения приложения
3. Разработчики увидят приятное сообщение, даже если доступ к данным в обход приложения
4. перемещение ограничений на триггеры - это ужасно (правда?), Поэтому я должен найти что-то отличное от Raise_Application_Error

EDIT2 Спустя 1,5 года, и после того, как я оставил работу, связанную с БД, мне наконец пришло в голову, что мне действительно не нравится в этом - дублирование кода . Я должен повторить ту же логику на сервере и на стороне клиента. Скорее всего, на 2 разных языках. И держать их в синхронизации. Это просто безобразно.

Хотя, как ясно указывают ответы, я ничего не могу с этим поделать. Поэтому мне пора стать хорошим гражданином и, наконец, принять ответ (извините, просто забыл об этом).

Ответы [ 4 ]

9 голосов
/ 20 мая 2011

Ограничения - это то, что базы данных используют для защиты себя от ошибочных приложений, не от пользователей.

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

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

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


Чтобы ответить на ваш настоящий вопрос, сообщения, которые приходят из Oracle для нарушений ограничений, не могутбыть изменен.Лучшее, что вы можете сделать, - это разумно назвать свои ограничения, чтобы они могли иметь смысл для конечного пользователя.

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

4 голосов
/ 20 мая 2011

Если вы ищете способ заставить Oracle всегда заменять сообщение об исключении «ORA-02290: проверка ограничения (SYS_C099871244) нарушено» другим сообщением, например «ORA-20001: Пол должен быть F или M», тогдаОтвет: нет, это не может быть сделано.

Что вы можете сделать, это предоставить решение, которое разработчики могут использовать в своем коде, примерно так:

...
begin
    insert into emp (empno, gender) values (p_empno, p_gender);
exception
    when others then
       error_pkg.handle_exception;
end;

The *Процедура 1006 * будет анализировать сообщение об исключении Oracle и извлекать имя ограничения (если оно было нарушением ограничения) и искать это имя ограничения в таблице перекрестных ссылок для получения требуемого сообщения, а затем использовать raise_application_erro r для повторного вызоваисключение с новым сообщением.

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

3 голосов
/ 20 мая 2011

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


Длинная версия:
Однако ваши причины хороши ...

Мне действительно нравится держать логику как можно ближе к данным

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

Для завершенияСообщение пользователя Raise_Application_Error неотличимо от сообщения приложения

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

Разработчики увидят приятное сообщение, даже если доступ к данным в обход приложения

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

Перемещениеограничения на триггеры - это некрасиво (правда?), поэтому я должен найти что-то отличное от Raise_Application_Error

Уродливо в том смысле, что это представление и не должно быть в DDL.Кроме того, он несет неоправданные (?) Потери производительности, если они выполняются с помощью триггеров (не уверен, насколько он велик или изящен).

Примечание. В целом я согласен, что было бы неплохо иметь возможность подключиться к обработке ошибок СУБД.

Однако обработка ошибок и обработка сообщений об ошибках имеют следующие свойства

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

и, что еще более важно

  • обработка сообщений об ошибках зависит от контекста (и обработчик ошибок будет наиболееинформирован с точки зрения клиента данных - иногда один и тот же код ошибки может потребовать другого представления, другого сообщения)
3 голосов
/ 20 мая 2011

Независимо от того, было ли ограничение введено клиенту или зарегистрировано в файле для (потенциального) анализа службой поддержки, у вас должно быть более полезное сообщение.

Если вы назовете ограничение, оно станет более полезным.

Я бы пошел на что-то вроде

ALTER TABLE blah ADD CONSTRAINT blah_gender_ck CHECK ( Gender IN ('F', 'M', 'OTHER'));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...