Как создать параметризованный запрос PDO с помощью оператора LIKE?


108

Вот моя попытка:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE "?%"');

$query->execute(array('value'));

while ($results = $query->fetch()) 
{
    echo $results['column'];
}

Ответы:


124

Я понял это сразу после того, как опубликовал:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('value%'));

while ($results = $query->fetch())
{
    echo $results['column'];
}

1
@ Андрей: а что, если использовать несколько like? как должен выполняться массив выполнения по порядку?
logan

Спасибо. была аналогичная проблема с использованием csharp + Mysql + ODBC, как будто он не возвращал никаких строк, используя «выберите * из таблицы, где столбец вроде '%?%';» но будет ли, если я сделаю так, как вы сделали «выбрать * из таблицы, где столбец вроде?;» и задайте строку параметра так: string frag = $ "% {searchFragment}%"; затем используйте frag для значения параметра. Weird
sdjuan 08

2
PDO должен экранировать этот% в вызове execute. Какай ответ лучше
Питер Багналл

Кажется , стоит отметить , что топ пользователей способствовали примечанию на PDOStatement :: bindParam документации страница предлагает другой подход: Добавить знак процента (ы) с переменным до его связывания.
Дэн Робинсон

Взгляните на решение Гэвина, взятое со страницы Your Common Sense в конце этой ветки. Просто. Логично.
RationalRabbit

85

Для тех , кто использует именованные параметры, вот как использовать LIKEс %частичным соответствием для баз данных MySQL :

WHERE имя_столбца LIKE CONCAT ('%',: dangerousstring, '%')

где именованный параметр :dangerousstring.

Другими словами, используйте явно неэкранированные %знаки в собственном запросе, которые разделены и определенно не вводятся пользователем.

Изменить: синтаксис конкатенации для баз данных Oracle использует оператор конкатенации : ||, поэтому он просто станет:

WHERE column_name LIKE '%' || : dangerousstring || '%'

Однако есть предостережения, поскольку @bobince упоминает здесь, что:

В Трудность возникает , когда вы хотите , чтобы в буквальном смысле %или _символ в строке поиска, без него выступать в качестве шаблона.

Так что это еще кое-что, на что следует обратить внимание при объединении лайков и параметризации.


6
+1 - это кажется мне хорошим подходом, так как вся конкатенация происходит в базе данных после замены заполнителя, и это означает, что можно использовать именованные заполнители. Стоит отметить, что приведенный выше синтаксис предназначен для Oracle - в MySQL синтаксис LIKE CONCAT('%', :something, '%'). Ссылка: stackoverflow.com/a/661207/201648
Аарон Ньютон

1
Это точно не сработало для меня, но привело меня на правильный путь. Мне нужно было сделать КАК "%": что-то "%", чтобы это сработало.
Кристофер Смит

Я знаю, что это не по теме, но я смог выполнить SQL-инъекцию даже с использованием этого статуса, почему?
Тьяго Диас

У меня это не сработало, я также тестировал его с помощью команды SQL, SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )это привело бы к ошибке.
Лузан Барал

@AaronNewton and it means named placeholders can be used. Как это вообще проблема с именованными заполнителями при объединении в PHP? Очевидно, что конкатенация в PHP поддерживает как именованные, так и позиционные, и более переносимая, поскольку вы можете использовать один и тот же запрос для любой базы данных. Я не понимаю , почему так много людей , думает , что есть какая - либо разница между именованным и позиционными заполнителями.
Ваш здравый смысл

18
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->bindValue(1, "%$value%", PDO::PARAM_STR);
$query->execute();

if (!$query->rowCount() == 0) 
{
    while ($results = $query->fetch()) 
    {
        echo $results['column'] . "<br />\n";
    }       
} 
else 
{
    echo 'Nothing found';
}

1
Есть ли преимущество в использовании этого ответа по сравнению с принятым ответом? Защищает ли использование bindValueот инъекционных атак? Принятый ответ в основном сводит на нет ценность использования ?заполнителей, объединяя строку поиска, %как в старые добрые времена.
felwithe

В чем смысл использования отрицания перед $ query-> rowCount () == 0? Есть ли в этом смысл?
ssi-anik

15

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

$query = $pdo_connection->prepare('SELECT * FROM table WHERE column LIKE :search');

$stmt= $pdo_connection->prepare($query);

$stmt->execute(array(':search' => '%'.$search_term.'%'));

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

print_r($result);

Я отредактировал ваше сообщение, чтобы поместить код в блок кода - вы можете узнать больше о форматировании сообщения на stackoverflow.com/help/formatting . Другой пользователь решил проголосовать против вашего ответа, не оставляя комментария, поэтому я не уверен в причине отрицательного голоса.
josliber

2
Повторяю, я не голосовал по вашему вопросу; кто-то еще проголосовал против.
josliber


2

Я получил это из-за заблуждений php

$search = "%$search%";
$stmt  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stmt->execute([$search]);
$data = $stmt->fetchAll();

И у меня это работает, очень просто. Как он говорит, вы должны «сначала подготовить наш полный литерал», прежде чем отправлять его в запрос.


0

PDO экранирует "%" (может привести к внедрению sql) : использование предыдущего кода даст желаемые результаты при поиске соответствия частичным строкам, НО, если посетитель вводит символ "%", вы все равно получите результаты, даже если вы этого не сделаете. нет ничего, что хранится в базе данных (это может привести к инъекциям sql)

Я пробовал много вариантов с тем же результатом, что PDO избегает "%" ведущих нежелательных / невозбужденных результатов поиска.

Я подумал, что им стоило поделиться, если кто-то нашел слово вокруг этого, поделитесь им


1
Это из руководства: us3.php.net/manual/en/pdo.prepared-statements.php Это еще один пост, посвященный теме: stackoverflow.com/questions/22030451/ ... Мне очень хотелось бы узнать ваше мнение о этот выпуск.
Ozkar R

1
Возможное решение (не проверено). Используйте CONCAT , например: $ sql = «ВЫБРАТЬ item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')»; Ссылка: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R

3
PDO не избегает%. Это ваш код делает это неправильно. Для решения вы должны прочитать ответы, уже предоставленные здесь
Your Common Sense

Спасибо за ваши предложения. В любом случае, протестированный код был кодом из руководства, с использованием заполнителя, чтобы избежать SQL-инъекции, я все еще получаю тот же результат. Пример № 6 Недопустимое использование заполнителя PDO экранирует% с использованием приведенного выше кода, а не моего кода. Я новичок в форуме и, возможно, не понимаю, как здесь работают процессы комментирования, публикации и репутации, я запомню это для следующего, потому что, исходя из предыдущего комментария, вам нужна репутация, чтобы помогать другим или оставлять комментарии. Спасибо.
Ozkar R
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.