Подготовленный оператор PDO возвращает 0 строк, но запрос работает нормально

У меня есть подготовленное заявление:

SELECT `e1`.`field_value` AS `county`,
       `e2`.`field_value` AS `venue_type`,
       `l`.`ID` AS `listing_id`,
       `l`.`ID` AS `id`,
       `l`.`user_ID` AS `user_id`,
       IF(`l`.`user_ID` > 1, 'b', 'a') AS `flag` ,
       COUNT(`img`.`ID`) AS `img_num`
FROM ( `listingsDBElements` `e1`,
       `listingsDBElements` `e2`,
       `listingsDB` `l` )
LEFT JOIN `listingsImages` `img` ON (`l`.`ID` = `img`.`listing_id`
                                     AND `l`.`user_ID` = `img`.`user_id`
                                     AND `img`.`active` = 'yes')
WHERE `e1`.`field_name` = 'county'
  AND `e1`.`field_value` = :county
  AND `l`.`ID` = `e1`.`listing_id`
  AND `l`.`user_ID` = `e1`.`user_id`
  AND `e2`.`field_name` = 'venue_type'
  AND `e2`.`field_value` = :venueType
  AND `l`.`ID` = `e2`.`listing_id`
  AND `l`.`user_ID` = `e2`.`user_id`
  AND `l`.`ID` = `e2`.`listing_id`
  AND `l`.`user_ID` = `e2`.`user_id`
  AND `l`.`active` = 'yes'
GROUP BY `l`.`ID`
ORDER BY `flag` DESC,
         `img_num` DESC LIMIT :limit,
                              :offset

Со следующими привязанными к нему параметрами:

:county => 'Bedfordshire'
:venueType => 'Conference Centre'
:limit => 0
:offset => 12

Затем я выполняю Подготовленный оператор с использованием PDO следующим образом:

$vens = $db->prepare($sql);

if($paged)
{
    $limit = (int) (($page - 1) * $perPage);
    $perPage = (int) $perPage;

    $vens->bindParam(':offset', $perPage, PDO::PARAM_INT);
    $vens->bindParam(':limit', $limit, PDO::PARAM_INT);
}

foreach($bindings as $key => $value) { $vens->bindParam($key, $value, PDO::PARAM_STR); }
$vens->execute();

while($ven = $vens->fetchObject())
{
    $_tpl['venues'][] = new Venue($ven->id);
}

Вышеупомянутое всегда возвращает 0 результатов, даже с использованием $db->rowCount(), но если я вручную запустил запрос и заменил заполнители в MySQL, будет получен ожидаемый результат из 4 записей. Что странно, у меня есть другой (почти идентичный) запрос, который выполняет и подсчитывает общее количество строк и связывает те же параметры следующим образом:

SELECT COUNT(DISTINCT(`l`.`ID`)) AS `total`
FROM ( `listingsDBElements` `e1`,
       `listingsDBElements` `e2`,
       `listingsDB` `l` )
WHERE `e1`.`field_name` = 'county'
  AND `e1`.`field_value` = :county
  AND `l`.`ID` = `e1`.`listing_id`
  AND `l`.`user_ID` = `e1`.`user_id`
  AND `e2`.`field_name` = 'venue_type'
  AND `e2`.`field_value` = :venueType
  AND `l`.`ID` = `e2`.`listing_id`
  AND `l`.`user_ID` = `e2`.`user_id`
  AND `l`.`ID` = `e2`.`listing_id`
  AND `l`.`user_ID` = `e2`.`user_id`
  AND `l`.`active` = 'yes'

И это выполняется с использованием:

$counter = $db->prepare($countSql);
$counter->execute($bindings);
$counts = $counter->fetchObject();

$counts->total правильно возвращает 4. Может ли кто-нибудь предложить, почему первый подготовленный оператор возвращает 0 строк через PDO, но отлично работает при ручном вводе в MySQL?

Изменить:

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

SELECT `l`.`ID` AS `id`,
       IF(`l`.`user_ID` > 1, 'b', 'a') AS `flag`
FROM `listingsDB` `l`
INNER JOIN `listingsDBElements` `e` ON `l`.`ID` = `e`.`listing_id`
WHERE `e`.`field_name` = 'city'
  AND `e`.`field_value` = :town
  AND `l`.`active` = 'yes'
ORDER BY `flag` DESC LIMIT :limit,
                           :offset

person BenM    schedule 07.03.2014    source источник
comment
Я подозреваю, что ваш результат 0 строк вызван синтаксической ошибкой, вы не можете привязать ограничение / смещение к параметрам.   -  person Joachim Isaksson    schedule 07.03.2014
comment
Вам не нужен цикл foreach / bind. Просто передайте привязки для выполнения.   -  person hek2mgl    schedule 07.03.2014
comment
@BenM Странно, в документации вроде бы сказано иначе, но раньше они ошибались :)   -  person Joachim Isaksson    schedule 07.03.2014
comment
@JoachimIsaksson см. Правку. Другие запросы с привязанными офетами и ограничениями работают нормально ...   -  person BenM    schedule 07.03.2014
comment
@BenM Просто подсказка, имея почти 20к, вы сможете упростить задачу до ее основ. В нынешнем виде он просто слишком усложняет   -  person hek2mgl    schedule 07.03.2014
comment
Вызов строк для пропуска limit и ограничения количества строк offset меня немного сбил с толку :)   -  person Joachim Isaksson    schedule 07.03.2014


Ответы (1)


По сути, вы можете связывать только определенные типы вещей в подготовленном заявлении.

Из руководства по MySQL:

Маркеры допустимы только в определенных местах в операторах SQL. Например, они разрешены в списке VALUES () оператора INSERT (для указания значений столбца для строки) или при сравнении со столбцом в предложении WHERE для указания значения сравнения. Однако они не разрешены для идентификаторов (таких как имена таблиц или столбцов) или для указания обоих операндов двоичного оператора, такого как знак = равно. Последнее ограничение необходимо, поскольку невозможно определить тип параметра. Как правило, параметры допустимы только в операторах языка обработки данных (DML), но не в операторах языка определения данных (DDL).

Обратите внимание, что LIMIT и OFFSET отсутствуют в списке разрешенных местоположений.

person Powerlord    schedule 07.03.2014