Учитывая массив идентификаторов, $galleries = array(1,2,5)
я хочу иметь запрос SQL, который использует значения массива в своем предложении WHERE, например:
SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */
Как я могу сгенерировать эту строку запроса для использования с MySQL?
Ответы:
источник
$galleries
должно быть подтверждено перед этим утверждением! Подготовленные операторы не могут обрабатывать массивы AFAIK, поэтому, если вы привыкли связывать переменные, вы можете легко сделать возможным внедрение SQL здесь.$galleries
имел следующее значение:array('1); SELECT password FROM users;/*')
. Если вы не очистите это, запрос будет читатьSELECT * FROM galleries WHERE id IN (1); SELECT password FROM users;/*)
. Измените имена таблиц и столбцов на те, которые есть в вашей базе данных, и попробуйте этот запрос, проверьте результаты. В качестве результата вы найдете список паролей, а не список галерей. В зависимости от того, как выводятся данные или что скрипт делает с массивом неожиданных данных, это может привести к выводу в публичное представление ... ой.$galleries
как указано в вопросе, и вы используете его, используя вышеупомянутую «уязвимость SQL-инъекций». Если вы не можете - вы платите мне 200 долларов США. Как насчет этого?Использование PDO: [1]
Использование MySQLi [2]
Объяснение:
Используйте
IN()
оператор SQL, чтобы проверить, существует ли значение в данном списке.В целом это выглядит так:
Мы можем построить выражение для размещения внутри
()
нашего массива. Обратите внимание, что в скобках должно быть хотя бы одно значение, иначе MySQL выдаст ошибку; это означает, что у нашего входного массива есть хотя бы одно значение. Чтобы предотвратить атаки с использованием SQL-инъекций, сначала?
создайте для каждого элемента ввода a для создания параметризованного запроса. Здесь я предполагаю, что массив, содержащий ваши идентификаторы, называется$ids
:Данный входной массив из трех элементов
$select
будет выглядеть так:Снова обратите внимание, что
?
для каждого элемента есть входной массив. Затем мы будем использовать PDO или MySQLi для подготовки и выполнения запроса, как указано выше.Использование
IN()
оператора со строкамиЛегко переключаться между строками и целыми числами из-за связанных параметров. Для PDO никаких изменений не требуется; для MySQLi измените
str_repeat('i',
на,str_repeat('s',
если вам нужно проверить строки.[1]: я упустил некоторые проверки ошибок для краткости. Вам нужно проверить обычные ошибки для каждого метода базы данных (или настроить драйвер БД на выдачу исключений).
[2]: Требуется PHP 5.6 или выше. Снова я пропустил некоторые проверки ошибок для краткости.
источник
$statement->bind_param(str_repeat('i', count($ids)), ...$ids);
то...
это расширение идентификаторов из массива на несколько параметров. Если вы имеете в виду,expr IN (value,...)
то это просто означает, что может быть больше значений, напримерWHERE id IN (1, 3, 4)
. Там просто должен быть хотя бы один....
: wiki.php.net/rfc/argument_unpackingИнтс:
строки:
источник
Предполагая, что вы правильно санируете свои данные заранее ...
Затем просто настройте ваш запрос:
Укажите значения соответственно в зависимости от вашего набора данных.
источник
Использование:
Простой
for each
цикл будет работать.Путь Flavius / AvatarKava лучше, но убедитесь, что ни одно из значений массива не содержит запятых.
источник
Как ответ Флавиуса Стефа , вы можете использовать,
intval()
чтобы убедиться, что всеid
значения int:источник
Для MySQLi с функцией escape:
Для PDO с подготовленным заявлением:
источник
Мы должны позаботиться об уязвимостях SQL-инъекций и пустом состоянии . Я собираюсь справиться с обоими, как показано ниже.
Для чистого числового массива, используйте соответствующее а именно преобразование типов
intval
илиfloatval
илиdoubleval
над каждым элементом. Для строковых типов,mysqli_real_escape_string()
которые могут также применяться к числовым значениям, если вы хотите. MySQL допускает числа, а также варианты даты в виде строки .Чтобы правильно экранировать значения перед передачей в запрос, создайте функцию, аналогичную следующей:
Такая функция, скорее всего, будет уже доступна вам в вашем приложении, или, возможно, вы уже создали ее.
Очистить массив строк следующим образом:
Числовой массив можно очистить с помощью
intval
илиfloatval
илиdoubleval
вместо этого, если это необходимо:Затем, наконец, построить условие запроса
или
Поскольку массив также иногда может быть пустым, как
$galleries = array();
мы должны заметить,IN ()
это не допускает пустой список. Можно также использоватьOR
вместо этого, но проблема остается. Таким образом, проверка выше,count($values)
чтобы обеспечить то же самое.И добавьте его в окончательный запрос:
источник
$query = 'SELECT * FROM galleries WHERE ' . (count($gallaries) ? "id IN ('" . implode("', '", array_map('escape', $gallaries)) . "')" : 0);
Безопаснее.
источник
Библиотека SafeMySQL для PHP полковника Шрапнеля предоставляет заполненные подсказки типа в своих параметризованных запросах и включает пару удобных заполнителей для работы с массивами.
?a
Заполнитель расширяется из массива в список разделенных запятыми беглых строк *.Например:
* Обратите внимание, что, поскольку MySQL выполняет автоматическое приведение типов, не имеет значения, что SafeMySQL преобразует идентификаторы выше в строки - вы все равно получите правильный результат.
источник
Мы можем использовать это предложение «WHERE id IN», если будем правильно фильтровать входной массив. Что-то вроде этого:
Как пример ниже:
Т.е. теперь вам следует смело пользоваться
$query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";
источник
Вы можете иметь стол
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)
:Таким образом, вы можете управлять простым отношением базы данных n2m без дополнительной таблицы и использовать только SQL без необходимости использования PHP или какого-либо другого языка программирования.
источник
Еще пример:
источник
Помимо использования запроса IN, у вас есть два варианта сделать это, так как в запросе IN есть риск уязвимости внедрения SQL. Вы можете использовать цикл, чтобы получить точные данные, которые вы хотите, или вы можете использовать запрос с ИЛИ регистр
источник
Безопасный путь без PDO:
(array)$ids
Приведите$ids
переменную в массивarray_map
Преобразуйте все значения массива в целые числаarray_unique
Удалить повторяющиеся значенияarray_filter
Удалить нулевые значенияimplode
Соедините все значения в выбор INисточник
Поскольку исходный вопрос относится к массиву чисел, а я использую массив строк, я не смог заставить данные примеры работать.
Я обнаружил, что каждая строка должна быть заключена в одинарные кавычки для работы с
IN()
функцией.Вот мое решение
Как вы можете видеть, первая функция оборачивает каждую переменную массива
single quotes (\')
и затем внедряет массив.ПРИМЕЧАНИЕ:
$status
не содержит одинарных кавычек в операторе SQL.Существует, вероятно, более хороший способ добавить цитаты, но это работает.
источник
$filter = "'" . implode("','",$status) . "'";
'
внутри строки? SQL-инъекция уязвима. Используйте PDO :: quote или mysqli_real_escape_string.Ниже приведен метод, который я использовал, используя PDO с именованными заполнителями для других данных. Чтобы преодолеть SQL-инъекцию, я фильтрую массив, чтобы принимать только те значения, которые являются целыми числами, и отвергаю все остальные.
источник
Основные методы предотвращения SQL-инъекций:
Использование подготовленных операторов и параметризованных запросов считается лучшей практикой, но если вы выберете метод экранирования символов, вы можете попробовать мой пример ниже.
Вы можете сгенерировать запросы с помощью
array_map
добавления одинарной кавычки к каждому из элементов в$galleries
:Сгенерированная переменная $ sql будет:
источник