Передача массива в запрос с использованием предложения WHERE - PullRequest
292 голосов
/ 25 мая 2009

Учитывая массив идентификаторов $galleries = array(1,2,5) Я хочу иметь запрос SQL, который использует значения массива в своем предложении WHERE, например:

SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */

Как я могу сгенерировать эту строку запроса для использования с MySQL?

Ответы [ 18 ]

4 голосов
/ 17 мая 2015

Col. Библиотека Shrapnel SafeMySQL для PHP предоставляет заполнители с подсказками типов в параметризованных запросах и включает пару удобных заполнителей для работы с массивами. Заполнитель ?a расширяет массив до разделенного запятыми списка экранированных строк *.

Например:

$someArray = [1, 2, 5];
$galleries = $db->getAll("SELECT * FROM galleries WHERE id IN (?a)", $someArray);

* Обратите внимание, что поскольку MySQL выполняет автоматическое приведение типов, не имеет значения, что SafeMySQL преобразует указанные выше идентификаторы в строки - вы все равно получите правильный результат.

4 голосов
/ 03 июня 2011

У вас может быть таблица texts (T_ID (int), T_TEXT (text)) и таблица test (id (int), var (varchar(255)))

В insert into test values (1, '1,2,3') ; следующие строки будут выводить строки из текстов таблицы, где T_ID IN (1,2,3):

SELECT * FROM `texts` WHERE (SELECT FIND_IN_SET( T_ID, ( SELECT var FROM test WHERE id =1 ) ) AS tm) >0

Таким образом, вы можете управлять простым отношением базы данных n2m без дополнительной таблицы и использовать только SQL без необходимости использования PHP или другого языка программирования.

3 голосов
/ 19 августа 2016

Еще пример:

$galleryIds = [1, '2', 'Vitruvian Man'];
$ids = array_filter($galleryIds, function($n){return (is_numeric($n));});
$ids = implode(', ', $ids);

$sql = "SELECT * FROM galleries WHERE id IN ({$ids})";
// output: 'SELECT * FROM galleries WHERE id IN (1, 2)'

$statement = $pdo->prepare($sql);
$statement->execute();
2 голосов
/ 27 января 2011

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

Я обнаружил, что каждая строка должна быть заключена в одинарные кавычки для работы с функцией IN().

Вот мое решение

foreach($status as $status_a) {
        $status_sql[] = '\''.$status_a.'\'';
    }
    $status = implode(',',$status_sql);

$sql = mysql_query("SELECT * FROM table WHERE id IN ($status)");

Как видите, первая функция оборачивает каждую переменную массива в single quotes (\'), а затем выполняет развертывание массива.

ПРИМЕЧАНИЕ: $status не содержит одинарных кавычек в операторе SQL.

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

2 голосов
/ 14 апреля 2015

Помимо использования запроса IN, у вас есть два варианта сделать это, так как в запросе IN есть риск уязвимости внедрения SQL. Вы можете использовать looping , чтобы получить точные данные, которые вы хотите, или вы можете использовать запрос с ИЛИ case

1. SELECT *
      FROM galleries WHERE id=1 or id=2 or id=5;


2. $ids = array(1, 2, 5);
   foreach ($ids as $id) {
      $data[] = SELECT *
                    FROM galleries WHERE id= $id;
   }
1 голос
/ 30 января 2018

Безопасный путь без PDO:

$ids = array_filter(array_unique(array_map('intval', (array)$ids)));

if ($ids) {
    $query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}
  • (array)$ids Приведение $ids переменная в массив
  • array_map Преобразовать все значения массива в целые числа
  • array_unique Удалить повторяющиеся значения
  • array_filter Удалить нулевые значения
  • implode Присоединить все значения к выбору IN
1 голос
/ 24 января 2018

Ниже приведен метод, который я использовал, используя PDO с именованными заполнителями для других данных. Чтобы преодолеть SQL-инъекцию, я фильтрую массив, чтобы принимать только значения, которые являются целыми числами, и отвергаю все остальные.

$owner_id = 123;
$galleries = array(1,2,5,'abc');

$good_galleries = array_filter($chapter_arr, 'is_numeric');

$sql = "SELECT * FROM galleries WHERE owner=:OWNER_ID AND id IN ($good_galleries)";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
    "OWNER_ID" => $owner_id,
));

$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
0 голосов
/ 10 апреля 2015

Основные методы предотвращения внедрения SQL:

  • Использовать подготовленные операторы и параметризованные запросы
  • Выход из специальных символов в вашей небезопасной переменной

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

Вы можете сгенерировать запросы, используя array_map, чтобы добавить одинарную кавычку к каждому из элементов в $galleries:

$galleries = array(1,2,5);

$galleries_str = implode(', ',
                     array_map(function(&$item){
                                   return "'" .mysql_real_escape_string($item) . "'";
                               }, $galleries));

$sql = "SELECT * FROM gallery WHERE id IN (" . $galleries_str . ");";

Сгенерированная переменная $ sql будет:

SELECT * FROM gallery WHERE id IN ('1', '2', '5');

Примечание: mysql_real_escape_string , как описано в его документации здесь , устарело в PHP 5.5.0 и удалено в PHP 7.0.0. Вместо этого следует использовать расширение MySQLi или PDO_MySQL. См. Также MySQL: выбор руководства по API и соответствующие часто задаваемые вопросы для получения дополнительной информации. Альтернативы этой функции включают в себя:

  • mysqli_real_escape_string ()

  • PDO :: цитата ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...