Почему мне нужно дважды экранировать (используйте 4 \), чтобы найти обратную косую черту ( \ ) в чистом SQL?

Я не понимаю такого поведения MySQL: если я хочу отобразить a\b, я могу просто выбрать "a\\b", которые работают без проблем:

mysql> select "a\\b";
+-----+
| a\b |
+-----+
| a\b |
+-----+
1 row in set (0.05 sec)

Но если я хочу найти строку, содержащую \ в таблице, используя LIKE, мне нужно дважды экранировать мой "\". Почему ?

Вот пример.

Готовим небольшой стол.

create table test ( test varchar(255) );
insert into test values ( "a\\b" ) , ( "a\\b\\c" ) , ( "abcd" );

mysql> select * from test;
+-------+
| test  |
+-------+
| a\b   |
| a\b\c |
| abcd  |
+-------+
3 rows in set (0.05 sec)

Мы пытаемся получить записи, начинающиеся с "a\b"...

mysql> select * from test where test LIKE "a\\b%";
+------+
| test |
+------+
| abcd |
+------+
1 row in set (0.05 sec)

Почему \\ там просто игнорируется? Почему мне нужно дважды экранировать basckslash, чтобы получить ожидаемый результат?

mysql> select * from test where test LIKE "a\\\\b%";
+-------+
| test  |
+-------+
| a\b   |
| a\b\c |
+-------+
2 rows in set (0.04 sec)

person Alain Tiemblo    schedule 16.11.2012    source источник


Ответы (2)


Вы экранируете сначала для синтаксиса строки, затем для синтаксиса LIKE.

В LIKE символы % и _ имеют особое значение, поэтому, если вы хотите искать литерал %, вам нужно использовать \%, а если вы хотите искать литерал \%, вам нужно экранировать обратную косую черту, как в \\%.

В синтаксисе строки ", очевидно, имеет особое значение, поэтому, если вы хотите включить кавычку в строку, вам нужно экранировать ее как \", а чтобы включить литерал \" в строку, вам нужно экранировать обратную косую черту, как в \\".

Таким образом, в обоих синтаксисах вам нужно экранировать \.


Если вы не хотите использовать \ для выхода из шаблона LIKE, вы можете использовать ключевое слово ESCAPE. Например:

...  where test LIKE "a\\b%" ESCAPE '|';

Таким образом, вам нужно будет написать |%, |_ или ||, чтобы избежать этих специальных символов.

person Kornel    schedule 16.11.2012
comment
Я думал о таком поведении, но это совершенно неестественно... Слишком много уровней парсинга. Только представьте, если мне нужно поместить такой запрос в PHP, мне нужно 4 раза экранировать обратную косую черту (поэтому используйте `\\\\\\\`), потому что PHP тоже имеет свой собственный интерпретатор. - person Alain Tiemblo; 16.11.2012
comment
Да, в самом деле. В строке PHP вам нужно еще раз сбежать. Вы можете думать об этом как о помещении данных в коробку. И если вы хотите найти его с помощью регулярного выражения в строке PHP, то еще больше убегаете! :) - person Kornel; 16.11.2012
comment
Позвольте мне не искать несколько `\` в LIKE :p - person Alain Tiemblo; 16.11.2012

См. раздел Функции сравнения строк.

Оператор like сравнивает с шаблоном, который может включать % и _. Чтобы избежать их, вы должны использовать \. Так что обратная косая черта тоже особый символ.

Когда вы вводите строку шаблона "a\\\\b", она интерпретируется Mysql, а затем снова аналогичным оператором, который дает "a\\b", а затем "a\b".

person Olaf Dietsche    schedule 16.11.2012