У меня есть хранимая процедура, которая принимает один параметр String — значение, передаваемое в этот параметр, представляет собой разделенный запятыми список идентификаторов из PHP — что-то вроде 2,3,4,5
`DECLARE tags_in VARCHAR(255);`
В хранимой процедуре я хотел бы выбрать строки, идентификаторы которых соответствуют идентификаторам в параметре — запрос будет выглядеть так:
`SELECT * from tags WHERE tag_id IN (tags_in)`
Я передаю значения из PHP в MySQL, используя следующий оператор, связывающий значение в виде строки
`$stmt->bindParam(':tags', '2,3,4', PDO::PARAM_STR);`
Проблема — фактический запрос, выполняемый MySQL, как показано ниже — где передаваемые параметры рассматриваются как одна строка
`SELECT * from tags WHERE tag_id IN ('2,3,4')`
Когда я хочу выполнить запрос, как показано ниже, параметры рассматриваются как отдельные целые числа
`SELECT * from tags WHERE tag_id IN (2,3,4)`
Любые предложения о том, как я могу это сделать?
Заполнители SQL могут представлять только ОДНО значения. Если вы передадите несколько значений, разделенных запятыми, они не будут восприниматься как несколько отдельных значений с запятыми, они будут рассматриваться как монолитная строка.
например
... WHERE foo IN (:bar)
... WHERE foo = :bar
функционально идентичны в том, что касается анализатора SQL, и он не учитывает передачу значений CSV. Оба будут выполняться одинаково:
... WHERE foo IN ('1,2,3')
... WHERE foo = '1,2,3'
Вам придется либо ограничить себя только таким количеством значений, сколько у вас есть заполнителей, либо динамически создать свой SQL и вставить заполнитель для каждого отдельного значения, которое вы пытаетесь вставить в IN
пункт.
например
$placeholders = array_fill(0, count($values_to_check) -1, '?');
$in_clause = implode(',', $placeholders);
/// builds ?,?,?,?,?,....?
$sql = "SELECT ... WHERE foo IN ($in_clause)";
$stmt = $dbh->prepare($sql);
$stmt->execute($values_to_check);
Это единственное место, где готовые операторы оказываются безрезультатными, и вам придется вернуться к старому доброму: «динамически создавать sql».
Иногда есть другой способ достичь желаемого результата, приведя целое число, которое вы пытаетесь сравнить, в виде строки, окруженной запятыми, и проверив, содержится ли результат в вашем списке возможных значений (с добавлением запятых также с обеих сторон). Возможно, он не самый эффективный для производительности, но позволяет вам делать то, что вы хотите, в одной процедуре или запросе.
Например (в вашем случае) что-то вроде этого может работать:
SELECT * from tags WHERE INSTR (CONCAT(',', tags_in, ','), CONCAT(',', tag_id, ',') );
MySql немного странный в том смысле, что он выполняет преобразование из int в char в функции CONCAT, некоторые другие базы данных требуют явного приведения.