SimBioT19
@SimBioT19
{{ user.about }}

Как сделать PDO + IN?

Как сделать запрос вида "UPDATE WHERE `id` IN ($sql)"
Нашёл кое-что, stackoverflow.com/questions/8991688/pdo-in-array-s...
но не ясно с bind`ом
Покажите пример!
У меня данный код не работает:
$query = $DB->prepare("UPDATE `Ttopic` SET `main`=:main, `main_id`=:theme,`type`='".$f['type']."' WHERE `id` IN ($q) limit 10");

$query->bindParam(':main', $main);
$query->bindParam(':theme', $theme);
if($query->execute($Ar)) echo 'ok';

По-моему с execute вообще неправильно
  • Вопрос задан
  • 7618 просмотров
Решения вопроса 1
orlov0562
@orlov0562 Куратор тега PHP
I'm cool!
Самый простой способ, взять ключи массива и по ним потом "прибиндить" данные, что-то типа:
$inValues = [1, 2, 3, 4];
	$inKeys = array_map(function($key){return ':var_'.$key;}, array_keys($inValues));
	
	$sql = 'SELECT * FROM `table` WHERE `field` IN ('.implode(',', $inKeys).')';
	
	echo $sql;
	
	$db = new PDO(...);
	$stmt = $db->prepare($sql);
	
	foreach($inValues as $key=>$val) {
		$stmt->bindParam(':var_'.$key, $val);
	}


с execute аналогично:

<?php

	$inValues = [1,2,3,4];
	
	$preparedInValues = array_combine(
		array_map(function($key) {
		   return ':var_'.$key;
		}, array_keys($inValues)),
		array_values($inValues)
	);
			
	$sql = 'SELECT * FROM `table` WHERE `field` IN ('.implode(',', array_keys($preparedInValues)).')';

	echo $sql;

	$db = new PDO(...);
	$stmt = $db->prepare($sql);
	$stmt->execute($preparedInValues);
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@heartdevil
плыву как воздушный шарик
Привет.

Вот вырезка

/* Execute a prepared statement using an array of values for an IN clause */
$params = array(1, 21, 63, 171);
/* Create a string for the parameter placeholders filled to the number of params */
$place_holders = implode(',', array_fill(0, count($params), '?'));

/*
    This prepares the statement with enough unnamed placeholders for every value
    in our $params array. The values of the $params array are then bound to the
    placeholders in the prepared statement when the statement is executed.
    This is not the same thing as using PDOStatement::bindParam() since this
    requires a reference to the variable. PDOStatement::execute() only binds
    by value instead.
*/
$sth = $dbh->prepare("SELECT id, name FROM contacts WHERE id IN ($place_holders)");
$sth->execute($params);


То есть, по сути, тебе можно вручную вот такую шнягу сделать
'WHERE id in (?,?,?,?,?,?,?)'

и собачить типизированные параметры

->bindParam(1, $id, PDO::PARAM_INT);
->bindParam(2, $id, PDO::PARAM_INT);
...

Но это за тебя сделает

вот эта штука

$place_holders = implode(',', array_fill(0, count($params), '?'));

насколько я понял.

тадам
Ответ написан
Комментировать
kimono
@kimono
Web developer
Честно, не проверял, но по вашей логике примерно следующее:
$values = [1, 2, 3];
$in_query = implode(',', array_fill(0, count($values), '?'));
$query = $DB->prepare(sprintf("UPDATE `Ttopic` SET `main`= ?, `main_id`= ?, `type`='".$f['type']."' WHERE `id` IN (%s) LIMIT 10", $in_query));
if($query->execute(array_merge([$main, $theme], $values)) echo 'ok';

Ну и конечно же `type`='".$f['type']."' в запросе это зло.
Ответ написан
Я для данной цели написал класс, который работает следующим образом
$stmt = false;//Требуется объявить так как передаётся в метод execute по ссылке
$params = array("ids"=>array(1,4,7));
$sql = "SELECT * FROM `users` WHERE `id` IN (:ids)";
nikolaevevgePDOIn::execute($pdo,$sql,$params,$stmt);

Сам код класса выложен тут: https://blog.ivru.net/?id=270
P.S. в моём случаи для формирования отчёта требовалось выполнить сразу ряд запросов в которых предполагалась передача массива значений в конструкцию IN(и даже нескольких массивов в несколько конструкций IN), поэтому применение данного класса вполне оправдано.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы