Предложение MySQL IN — сравнение строк и INT

У меня есть хранимая процедура, которая принимает один параметр 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)`

Любые предложения о том, как я могу это сделать?

0

Решение

Заполнители 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».

1

Другие решения

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

Например (в вашем случае) что-то вроде этого может работать:

SELECT * from tags WHERE INSTR (CONCAT(',', tags_in, ','), CONCAT(',', tag_id, ',') );

MySql немного странный в том смысле, что он выполняет преобразование из int в char в функции CONCAT, некоторые другие базы данных требуют явного приведения.

0

По вопросам рекламы [email protected]