Есть ли способ дать удобное сообщение об ошибке при нарушении ограничений

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

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

Единственный способ, с помощью которого я могу думать, это переместить ограничения на триггер ДОПОЛНЕНИЯ ИЛИ ВСТАВКИ и при неудаче сделать Raise_Application_Error( code, my_message ). Но мне это не нравится

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

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

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

Ответ 1

Если вы ищете способ сообщить 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;

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

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

Ответ 2

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

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

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

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


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

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

Ответ 3

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

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

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

ALTER TABLE blah ADD CONSTRAINT blah_gender_ck CHECK ( Gender IN ('F', 'M', 'OTHER'));

Ответ 4

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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