Как предотвратить ошибку недопустимых символов в запросе DB2 SQL?

Я работаю с огромной таблицей DB2 (сотни миллионов строк), пытаясь выбрать только те строки, которые соответствуют этому регулярному выражению:

\b\d([- \/\\]?\d){12,15}(\D|$)

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

После долгих поисков мне удалось создать следующий SQL:

SELECT idx, comment FROM tblComment
WHERE xmlcast(xmlquery('fn:matches($c,"\b\d([- \/\\]?\d){12,15}(\D|$)")' PASSING comment AS "c") AS INTEGER)=1

Который работает отлично, насколько я могу судить... если он не находит строку с недопустимым символом:

Недопустимый символ XML "#x3" был найден в выражении или аргументе функции SQL/XML, который начинается со строки [...]

Данные содержат много недопустимых символов XML, и изменение данных не вариант (у меня ограниченный доступ только для чтения, и слишком много строк, которые необходимо исправить). Есть ли способ удалить или игнорировать недопустимые символы, не изменяя базу данных? Или есть другой способ написать мой запрос, который имеет такой же эффект?

1 ответ

Решение

Вам нужно будет определить, какие все недопустимые символы XML встречаются в ваших данных. Как только вы их знаете, вы можете использовать TRANSLATE() функция, чтобы устранить их во время сопоставления с образцом.

Скажем, вы определяете, что все управляющие символы ASCII (от 0x00 до 0x0F и 0x7F) могут присутствовать в COMMENT колонка. Ваш запрос может выглядеть так:

SELECT idx, comment FROM tblComment
WHERE xmlcast(xmlquery(
  'fn:matches($c,"\b\d([- \/\\]?\d){12,15}(\D|$)")' 
  PASSING TRANSLATE(comment, ' ', x'01020304050607080B0C0F7F') AS "c") 
AS INTEGER)=1

Все допустимые символы XML перечислены в руководстве. 0x09, 0x0A и 0x0D допустимы, поэтому вам не нужно TRANSLATE() их, например.

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