Як створити параметризований запит PDO з оператором LIKE?


107

Ось моя спроба на це:

$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
@Andrew: що робити, якщо likeвикористовується декілька ? як повинен виконуватися масив файлів для виконання?
логан

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

2
PDO повинен уникати цього% у виклику виконання. Відповідь Какая краща
Пітер Баньялл

Здається , варто відзначити , що топ користувачів сприяли приміткою на PDOStatement :: bindParam документації сторінка пропонує інший підхід: Додати знак відсотка (и) зі змінним до його зв'язування.
Ден Робінсон

Подивіться на рішення Гевіна, взяте зі сторінки Вашого здорового глузду, внизу цієї теми. Простий. Логічні.
RationalRabbit

85

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

WHERE_ ім'я стовпця LIKE CONCAT ('%',: dangerousstring, '%')

де вказаний параметр :dangerousstring.

Іншими словами, використовуйте %у власному запиті явно нерозміщені знаки, які відокремлюються і, безумовно, не вводяться користувачами.

Редагувати: Синтаксис конкатенації для баз даних Oracle використовує оператор конкатенації:, ||тому він просто стане:

WHERE_ ім'я стовпця LIKE '%' || : небезпечний рядок || '%'

Однак є застереження, як @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

14

Ви також можете спробувати цей. Я стикаюся з подібною проблемою, але отримав результат після досліджень.

$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 / ... я owuld дійсно хотів би знати Вашу думку про це питання.
Ozkar R

1
Можливе рішення (Не перевірено) Використовуйте CONCAT , як-от: $ sql = «ВИБІРТЕ item_title З елемента, ЩО item_title LIKE CONCAT ('%',?, '%')»; Довідка: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R

3
PDO не уникає%. Це ваш код, який робить це неправильно. На вирішення ви повинні прочитати відповіді, які вже надані тут
Ваше здорове почуття,

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