@MisTFoR

Как решить проблему PDOStatement::execute(): SQLSTATE[HY093]?

Здравствуйте!
Изучаю php, написал код, но возникает ошибка: Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in (путь)

Код:
$product_Id = 32;
$sql = "SELECT * FROM `products` WHERE '$query'";
$query = $db->prepare($sql);
$query->execute(array(":product_Id1" => $product_Id));
$products_data = $query->fetchAll(\PDO::FETCH_ASSOC);


$query во второй строке хранит "(productId = 30) OR (productId = 32) OR (productId = 38)"

БД ниже на скрине приложил
6650cdfa0b494766554734.png
  • Вопрос задан
  • 69 просмотров
Решения вопроса 4
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Камрад alexalexes мыслит в правильном направлении, но как все новички, пишет очень много ненужного кода.
Вот более простое решение, которое и можно рекомендовать в этом случае:
$product_list = [30, 32, 38];
// получаем строку вида ?,?,? по количеству эл-тов в массиве
$placeholder_string = str_repeat('?,', count($product_list) - 1) . '?'; 
$sql = "SELECT * FROM `products` WHERE `productId` in ($placeholder_string)";
$query = $db->prepare($sql);
$query->execute($product_list); 
$products_data = $query->fetchAll(\PDO::FETCH_ASSOC);
Ответ написан
Комментировать
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Как вы пишете, в query у вас три id, а передаёте в execute вы только один, о чём вам прямым текстом сообщают.
Ответ написан
Комментировать
Melkij
@Melkij
PostgreSQL DBA
Если внимательно посмотреть на то что действительно написано, то это будет
$products_data = [];
if ($query) {
    $sql = "SELECT * FROM `products`";
    $products_data = $db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
}


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

Потому что where строковой_литерал это или заведомо невыполнимый запрос, 0 строк (если строковой литерал пустая строка) или истина для всех строк таблицы. Почему это строковой литерал? Ну, потому что таков синтаксис SQL, строка в одинарных кавычках - литерал.

А вот что вы подразумевали дальше, мне догадаться сложнее. Если в $query записано то что в вопросе, то что тогда такое должно быть :product_Id1?
Ответ написан
@alexalexes
Если вы вставляете в запрос список числовых параметров, то можно провернуть такое.
$product_list = [30, 32, 38];
$query = " `productId` in (".join(', ', array_map(function($item){return int $item;}, $product_list)).")";
$sql = "SELECT * FROM `products` WHERE ".$query;
// Должен получиться запрос:
// SELECT * FROM `products` WHERE `productId` in (30, 32, 38)
// array_map тут нужен для принудительного перевода всех значений в числовой вид, обеспечив тем самым экранирование.
$query = $db->query($sql);
$products_data = $query->fetchAll(\PDO::FETCH_ASSOC);

Если применять нормальную связку параметров PDO, как должны учить в учебниках:
$product_list = [30, 32, 38];
$in_params = [];
for($i = 0; $i < count($product_list), $i++)
  $in_params[':productId'.$i] = $product_list[$i];
// получили массив: $in_params = [':productId0' => 30, ':productId1' => 32, ':productId0' => 38];
$placeholder_string = join(', ', array_keys($in_params));
// получили строку $placeholder_string = ":productId0, :productId1, :productId2";
$sql = "SELECT * FROM `products` WHERE `productId` in (".$placeholder_string.")";
// Должен получиться запрос:
// SELECT * FROM `products` WHERE `productId` in (:productId0, :productId1, :productId2)
$query = $db->prepare($sql);
$query->execute($in_params); // in_params в точности в таком формате, который нужен для связки параметров productId
$products_data = $query->fetchAll(\PDO::FETCH_ASSOC);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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