Извлечь часть строки с помощью REGEXP_SUBSTR

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

Пример: ORA-01400: невозможно вставить NULL в («ABC_OWNER». «ABC_PART». «REGION»)

это нужно изменить на «Невозможно вставить NULL в REGION»

Я пробовал REGEXP_SUBSTR искать шаблон "ORA-" и делать некоторые извлечения, но мне это удалось только в определенной степени. Не могли бы вы посоветовать, как это сделать.

С Уважением.


person pats4u    schedule 25.10.2016    source источник
comment
Что вы пробовали? Также: вы не просто удалили код ошибки, вы также изменили сообщение: вы просто показываете, в какой столбец нельзя вставить NULL, а не схему и таблицу. Поможет ли это вам или окажется плохой идеей в будущем?   -  person mathguy    schedule 25.10.2016
comment
В реальном случае использования мне не нужно показывать схему или таблицу, поскольку пользователь загружает данные в таблицу и уже знает об этом. пользователю просто нужно знать, есть ли какая-либо ошибка во время загрузки. В моей реализации я объединяю загруженные пользователем данные в фактическую таблицу и регистрирую любую ошибку в таблице журнала ошибок и возвращаю эти ошибки обратно, если таковые имеются. Я просто хочу, чтобы он был простым и читаемым без кодов ошибок, имен схем и т. Д. Спасибо.   -  person pats4u    schedule 26.10.2016


Ответы (2)


есть много исключений n oracle и есть разные маски, вы хотите закодировать их все?

Текущее регулярное выражение может выглядеть так:

select regexp_replace('ORA-01400: cannot insert NULL into ("ABC_OWNER"."ABC_PART"."REGION")'
                     ,'^ORA-\d+:\s(.+)\(.+\.\"(.+)\"\)', '\1 \2') from dual

EDIT: описание регулярного выражения '^ORA-\d+:\s(.+)(.+.\"(.+)\")'

  1. "^" - начало строки
  2. "ORA-" - простая строка "ORA-"
  3. "\d+" - серия цифр
  4. ":" - простое двоеточие
  5. "\s" - пробел
  6. "(.+)" - самая длинная строка из любых символов. И () означает, что он будет захвачен как группа (\1).
  7. "(" - левая скобка
  8. ".+" - самая длинная строка из любых символов.
  9. "."- простая точка
  10. \" - двойная кавычка
  11. (.+) - самая длинная строка из любых символов. И следующая группа (\2)
  12. \" - двойная кавычка
  13. )' - правая скобка

Regexp в пунктах 6,8 и 11 будет голодным поиском, он попытается найти самую длинную строку из первой группы. Это означает, что есть варианты между длинами "6", "8" и "11". «6» выберет первым и возьмет все, что сможет, «8» выберет следующим, а «11» наименьшим. Например, если у вас есть строка aaaaaa и регулярное выражение (.+)(.+), первая группа примет aaaaa, а вторая a

person Michael Piankov    schedule 25.10.2016
comment
Спасибо, Майкл. Был бы очень признателен, если бы вы могли немного объяснить, как это на самом деле работает. - person pats4u; 26.10.2016
comment
Спасибо Михаил за объяснение. Если ошибка была ORA-12899: слишком большое значение для столбца ABC_OWNER.ABC_PART.REGION (фактическое: 6, максимальное: 4), как мы можем изменить это на: слишком большое значение для столбца REGION. Оба могут быть покрыты одним и тем же выражением регулярного выражения. - person pats4u; 26.10.2016
comment
Я думаю, вы можете попробовать что-то вроде regexp_replace(' ORA-12899: value too large for column "ABC_OWNER"."ABC_PART"."REGION" (actual: 6, maximum: 4)' '^\s*ORA-\d+:\s(.+?)\(?(\".+\"\.)?(\".+\"\.)?\"(.+)\"\)?.*' , '\1\4') - person Michael Piankov; 26.10.2016
comment
Ух ты ! это было быстро и идеально. Спасибо - person pats4u; 26.10.2016
comment
Привет, Майкл! Не могли бы вы помочь с regexp_replace для перевода ORA-00001: уникальное ограничение (SCOTT.SYS_C0010807) нарушено на дубликаты в файле. - person pats4u; 15.05.2017

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

with
     error_messages ( str ) as (
       select 'ORA-01400: cannot insert NULL into ("ABC_OWNER"."ABC_PART"."REGION")' 
         from dual
     )
select substr( str, instr(str, ' ') + 1) as modified_err_msg from error_messages
;

MODIFIED_ERR_MSG
----------------
cannot insert NULL into ("ABC_OWNER"."ABC_PART"."REGION")
person mathguy    schedule 25.10.2016