Использование NOT LIKE в Oracle - PullRequest
1 голос
/ 09 февраля 2020

Это может быть глупый вопрос - я надеюсь, что это не так - но я до сих пор не понимаю, почему этот код не работает на Oracle, а работает на сервере MS SQL.

Код:

SELECT DISTINCT CITY FROM STATION
WHERE CITY NOT LIKE '[AEIOUaeiou]%'
ORDER BY CITY ASC;

Код дает мне все города, которые не начинаются с гласных в SQL Сервере, но дает мне все города, когда я его запускаю в Oracle.

Почему это?

Ответы [ 3 ]

5 голосов
/ 09 февраля 2020

SQL Сервер поддерживает небольшое подмножество регулярных выражений в шаблоне LIKE. Oracle нет, но имеет всестороннюю поддержку регулярных выражений с функциями regexp_*.

Здесь вы можете использовать regexp_like():

SELECT DISTINCT CITY FROM STATION
WHERE NOT REGEXP_LIKE(CITY, '^[aeiou]', 'i')
ORDER BY CITY ASC;

Regex ^[aeiou] означает: один из перечисленных символов в начале строки (что означает '^'). Третий аргумент, называемый параметр соответствия : 'i', делает поиск нечувствительным к регистру.

3 голосов
/ 09 февраля 2020

Ваша попытка не работает, потому что в Oracle условия LIKE / NOT LIKE выполняют , а не , работают с регулярными выражениями. Вместо этого есть только два (или три) метасимвола: % (который вы пытались использовать правильно), подчеркивание, которое заменяет ровно один символ, и, возможно, экранирующий символ (если вам нужно экранировать % или _), которое должно быть объявлено в условии LIKE / NOT LIKE. Все остальное - буквальные символы. Название города не начинается с подстроки [AEIOUaeiou] (12 символов). Это - это то, что мешало вашему состоянию; так что, действительно, это не помешало каким-либо именам быть включенными в вывод.

GMB дал вам 100% правильное решение, в духе вашего вопроса - использование регулярных выражений.

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

Здесь простое и эффективное решение, использующее только стандартные строковые функции: Абсолютно возможно и относительно просто.

select city
from   station
where  substr(city, 1, 1) not in ('A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u')
;

Конечно, это можно изменить различными способами; Например, мы могли бы использовать lower(), чтобы избежать повторения гласных в верхнем и нижнем регистре. Или даже:

select city
from   station
where  'aeiou' not like '%' || lower(substr(city, 1, ,1)) || '%'
;

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

Обратите внимание, что в select я пропустил "разные" пункт, поскольку это совершенно не связано с вопросом. Всегда старайтесь, чтобы вопросы были как можно более мелкими, и в то же время полностью отражали фактически задаваемый вопрос.

2 голосов
/ 09 февраля 2020
WHERE CITY NOT LIKE '[AEIOUaeiou]%'

Код дает мне все города, которые не начинаются с гласных на SQL Сервере, но дает мне все города, когда я запускаю его на Oracle.

Почему это так?

Ответ на ваш вопрос заключается в том, что SQL Сервер расширил функциональность LIKE, включив в него диапазоны символов - к сожалению, оставляя большую часть того, что еще полезно в обычном выражения. Ну, собственно, SQL Сервер этого не делал. Sybase сделал, и Microsoft приобрела кодовую базу у Sybase. Таким образом, эти две базы данных поддерживают расширенную функциональность LIKE. (Я мог бы добавить, что MS Access также имеет нечто подобное.)

Большинство других баз данных имеют добросовестную поддержку регулярных выражений, поддерживаемую с помощью функций (таких как regexp_like() в Oracle или операторов например '~' в Postgres и regexp в MySQL). Они обрабатывают шаблон LIKE, такой как '[AEIOUaeiou]%', точно так же, как он говорит: они будут соответствовать строке, которая начинается с 12 указанных c символов - '[', 'A' и так далее. Поскольку ни одно из названий городов не начинается с [, намного меньше, чем после десяти гласных, ни один город не соответствует шаблону - и все равно передайте NOT LIKE logi c.

Кроме того, на сервере SQL сравнения обычно не чувствительны к регистру, поэтому '[A]' будет соответствовать 'A' и 'a'. Вы могли бы упростить выражение в этой базе данных. С другой стороны, в Oracle сравнения обычно чувствительны к регистру, поэтому вам нужно быть осторожным.

Я думаю, что GMB объяснил, как использовать регулярные выражения для того, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...