Буквальная интерпретация метасимволов в шаблонах

Задача
Вы хотите выполнить поиск по образцу, в который входит специальный символ, так, чтобы этот символ интерпретировался буквально, а не как специальный.

Решение
Экранируйте специальный символ при помощи обратного слэша. Или даже двух.

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

mysql> SELECT c FROM metachar;

+ -----+
| c |
+----- +
| % |
| _ |
| . |
| ^ |
| $ |
| \ |
+ -----+

Образец, состоящий только из метасимволов SQL, соответствует всем значениям таблицы, кроме самих метасимволов:

mysql> SELECT c, c LIKE '%', c LIKE '_' FROM metachar;

+----- + ------------+----------- +
| c | c LIKE '%' | c LIKE '_' |
+ -----+------------ +----------- +
| % | 1 | 1 |
| _ | 1 | 1 |
| .


| 1 | 1 |
| ^ | 1 | 1 |
| $ | 1 | 1 |
| \ | 1 | 1 |
+------ +------------ + -----------+

Для того чтобы в запросе использовались буквальные значения метасимволов SQL, оставьте перед образцом обратный слэш:

mysql> SELECT c, c LIKE '\%', c LIKE '\_' FROM metachar;

+ ----+ -------------+------------- +
| c | c LIKE '\%' | c LIKE '\_' |
+---- +-------------- +------------ +
| % | 1 | 0 |
| _ | 0 | 1 |
| . | 0 | 0 |
| ^ | 0 | 0 |
| $ | 0 | 0 |
| \ | 0 | 0 |
+ -----+-------------- +----------- +

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

mysql> SELECT c, c REGEXP '.', c REGEXP '^', c REGEXP '$' FROM metachar;

+ ----+---------------- + ---------------+---------------- +
| c | c REGEXP '.' | c REGEXP '^' | c REGEXP '$' |
+ ----+---------------- + ---------------+---------------- +
| % | 1 | 1 | 1 |
| _ | 1 | 1 | 1 |
| .


| 1 | 1 | 1 |
| ^ | 1 | 1 | 1 |
| $ | 1 | 1 | 1 |
| \ | 1 | 1 | 1 |
+---- + ---------------+---------------- +--------------- +

Для буквальной интерпретации метасимволов нужно просто добавить обратный слэш, не так ли? Давайте попробуем:

mysql> SELECT c, c REGEXP '\.', c REGEXP '\^', c REGEXP '\$' FROM metachar;

+ ----+---------------- +----------------- + ----------------+
| c | c REGEXP '\.' | c REGEXP '\^' | c REGEXP '\$' |
+ ----+ ----------------+----------------- +---------------- +
| % | 1 | 1 | 1 |
| _ | 1 | 1 | 1 |
| . | 1 | 1 | 1 |
| ^ | 1 | 1 | 1 |
| $ | 1 | 1 | 1 |
| \ | 1 | 1 | 1 |
+---- + ---------------+ ------------------+ ----------------+

Ничего не получилось, потому что регулярные выражения обрабатываются несколько иначе, чем шаблоны SQL.


Если вы используете REGEXP, то для буквальной интерпретации метасимволов потребуются два обратных слэша:

mysql> SELECT c, c REGEXP '\\.', c REGEXP '\\^', c REGEXP '\\$' FROM metachar;

+---- +----------------- +------------------ +----------------- +
| c | c REGEXP '\\.' | c REGEXP '\\^' | c REGEXP '\\$' |
+---- + -----------------+------------------ +----------------- +
| % | 0 | 0 | 0 |
| _ | 0 | 0 | 0 |
| . | 1 | 0 | 0 |
| ^ | 0 | 1 | 0 |
| $ | 0 | 0 | 1 |
| \ | 0 | 0 | 0 |
+---- + ----------------+ -------------------+ -----------------+

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

mysql> SELECT c, c LIKE '\\', c REGEXP '\\\\' FROM metachar;

+---- +------------ +----------------- +
| c | c LIKE '\\' | c REGEXP '\\\\' |
+---- + ------------+ -----------------+
| % | 0 | 0 |
| _ | 0 | 0 |
| . | 0 | 0 |
| ^ | 0 | 0 |
| $ | 0 | 0 |
| \ | 1 | 1 |
+---- +------------ +----------------- +

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

Внутри класса символов для включения в него используемых в нем же символов следуйте таким правилам:
• Для включения литерала ] укажите его первым в списке.
• Для включения литерала укажите его первым или последним.
• Для включения литерала ^ укажите его не первым.
• Для включения литерала \ продублируйте его.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела MySQL на эту тему:
FULLTEXT поиск и короткие слова
Включение и исключение слов из FULLTEXT - поиска
Поиск по образцу с помощью регулярных выражений
Поиск по образцу с помощью шаблонов SQL
Поиск с помощью индекса FULLTEXT

Вернуться в раздел: MySQL / 4. Работа со строками