2016-06-14 2 views
3

У меня есть странное поведение для следующего запроса, содержащего регулярное выражение:Regex в многоязычном запросе не работает для приложения, но в разработчика SQL и модульного тестирования

SELECT COALESCE(lang.TITLE, ids.message_id) AS TEXT, 
    ids.message_id 
FROM 
    (SELECT 
    CASE 
     WHEN regexp_instr(messages.NR, '[a-z]{2}[[:space:],_-]\d+[-_]\d{2,6}') > 0 
     THEN regexp_substr(messages.NR, '\d+') 
     ELSE messages.NR 
    END AS message_id 
    FROM 
    (SELECT 'GB 28647854-04' AS NR FROM dual 
    UNION 
    SELECT 'GB 5310031-05' AS NR FROM dual 
    UNION 
    SELECT '9184' AS NR FROM dual 
    ) messages 
) ids, 
    LOCAL_TITLES lang 
WHERE ids.message_id = '' || lang.NUMBER_NO(+); 

LOCAL_TITLES содержит следующие данные:

  • 5310031 | Некоторые локализованные Текст
  • 9184 | Другой текст

Так ожидаемый результат запроса должен быть:

  • 28647854 | 28647854
  • Некоторые локализованные текст | 5310031
  • Другой текст | 9184

Это хорошо работает, когда запрос выполняется через SQL Developer. Также у меня есть (Unit-/Integration-) Test для моего DAO, который запускает этот запрос, возвращая ожидаемый результат.

Моя проблема: когда запрос выполняется запущенным веб-приложением, то регулярное выражение не находит числовой идентификатор. Вместо этого, результат фактического запроса является

  • GB 28647854-04 | GB 28647854-04
  • GB 5310031-05 | GB 5310031-05
  • Другой текст | 9184

У вас есть идея, почему регулярное выражение ведет себя по-другому, когда оно происходит из веб-приложения?

+0

Разве ваше веб-приложение не использует DAO для доступа к данным? Поскольку DAO, похоже, работает (по крайней мере, ваши тесты, похоже, указывают на это), все должно быть хорошо. Таким образом, вы либо выполняете этот запрос/выражение каким-либо другим способом, либо ваш тест имеет какую-то другую настройку. В любом случае нам, вероятно, нужна дополнительная информация. – Thomas

+0

Настройка действительно немного отличается от реализации java.sql.Connection: в веб-приложении используется «PooledConnection», тогда как во время тестовых прогонов мы называем «DriverManager.getConnection()». Помимо этого, нет никакой разницы в реализации. Веб-приложение работает на сервере Weblogic 12c. –

+0

Обратите внимание, что это может быть не только разница в реализации, но также в конфигурации, библиотеках (например, другом JDBC-драйвере) и т. Д. – Thomas

ответ

2

Ваше регулярное выражение ищет строчные буквы с шаблоном [a-z]. Ваши двойные сгенерированные данные имеют прописные ГБ, так что они не совпадают с настройками с учетом регистра по умолчанию, по крайней мере, в моей местности:

alter session set nls_sort = 'BINARY'; 

SELECT 
    CASE 
     WHEN regexp_instr(messages.NR, '[a-z]{2}[[:space:],_-]\d+[-_]\d{2,6}') > 0 
     THEN regexp_substr(messages.NR, '\d+') 
     ELSE messages.NR 
    END AS message_id 
    FROM 
    (SELECT 'GB 28647854-04' AS NR FROM dual 
    UNION 
    SELECT 'GB 5310031-05' AS NR FROM dual 
    UNION 
    SELECT '9184' AS NR FROM dual 
    ) messages; 

MESSAGE_ID 
-------------- 
9184   
GB 28647854-04 
GB 5310031-05 

Если вы сделаете сеанс регистронезависимыми они делают:

alter session set nls_sort = 'BINARY_CI'; 

SELECT 
    CASE 
     WHEN regexp_instr(messages.NR, '[a-z]{2}[[:space:],_-]\d+[-_]\d{2,6}') > 0 
     THEN regexp_substr(messages.NR, '\d+') 
     ELSE messages.NR 
    END AS message_id 
    FROM 
    (SELECT 'GB 28647854-04' AS NR FROM dual 
    UNION 
    SELECT 'GB 5310031-05' AS NR FROM dual 
    UNION 
    SELECT '9184' AS NR FROM dual 
    ) messages; 

MESSAGE_ID 
-------------- 
9184   
28647854  
5310031  

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

SELECT 
    CASE 
     WHEN regexp_instr(messages.NR, '[a-z]{2}[[:space:],_-]\d+[-_]\d{2,6}', 1, 1, 0, 'i') > 0 
     THEN regexp_substr(messages.NR, '\d+', 1, 1, 'i') 
     ELSE messages.NR 
    END AS message_id 
... 

Или просто расширить класс персонажа:

 WHEN regexp_instr(messages.NR, '[a-zA-Z]{2}[[:space:],_-]\d+[-_]\d{2,6}') > 0 

или

 WHEN regexp_instr(messages.NR, '[[:alpha:]]{2}[[:space:],_-]\d+[-_]\d{2,6}') > 0 

Некоторые из ваших сеансов создаются с BINARY_CI (или некоторых других регистронезависимых) linguistic comparison настройки, но ваши настройки «веб-приложения» не является. Это может быть до уровня, который используется для каждого из них, поэтому изменение языкового стандарта приложения также может устранить несоответствие; но сделать логику более логичным, вероятно, лучше.

Более конкретно, в вашем случае (если смотреть в вашем профиле), если ваш язык - Германия, то ваш NLS_SORT - немецкий, который ведет себя так же, как BINARY_CI, для меня с британским языковым стандартом. Предположительно, ваш SQL Developer и модульный тест запускаются с немецкими настройками, а ваше веб-приложение - не из-за собственных настроек по умолчанию или по дизайну.

Read more about "SQL Regular Expressions in a Multilingual Environment" in the documentation.

+0

Perfect. Я отредактировал OP, чтобы отразить это решение. –

 Смежные вопросы

  • Нет связанных вопросов^_^