Экранирующий столбец для использования в ПОДОБНОМ выражении

#mysql #escaping

#mysql #экранирование

Вопрос:

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

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

 SELECT * FROM `files` WHERE '<request-url>' LIKE CONCAT(`url`, '%')
 

Этот вид работ, но он приводит к ложным срабатываниям. Если, например, URL-адрес файла /file/my_file.pdf равен, URL-адреса like /file/my1file.pdf могут использоваться для доступа к файлу, поскольку _ это подстановочный LIKE знак .

Как я могу экранировать столбец url , чтобы его можно было надежно использовать в LIKE выражениях?

Бонусный вопрос: что, если мне нужно было использовать REGEXP выражение вместо этого?

Ответ №1:

Вы можете заменить _ и % на _ и % , чтобы избежать их.

 LIKE CONCAT(REPLACE(REPLACE(url, '_', '\_'), '%', '\%'), '%')
 

Другой вариант — не использовать LIKE

 WHERE LOCATE(url, '<request-url>') = 1
 

Комментарии:

1. Если OP ищет столбец url , который является префиксом входного запроса, что и предлагает его SQL (язык немного неоднозначен — см. Мой ответ), тогда вам нужно ` WHERE LOCATE (‘<request-url>’, url) = 0`

2. Я думаю, что мой правильный. Синтаксис LOCATE(substring, fullstring)

3. Нет проблем, у меня также возникают проблемы с запоминанием порядка аргументов функций MySQL. Обычно аргумент, который, вероятно, будет столбцом, является первым, поэтому было бы более последовательно, чтобы он был таким, как вы говорите.

4. Это делает мой ответ излишним.

5. Приятно @Barmar! Предположим, я пошел с REPLACE решением, разве мне не пришлось бы также избегать уже существующего «?