Использовать подготовленную инструкцию в запросе с предложением ‘IN (…..)’?

#php #pdo

#php #pdo

Вопрос:

Есть ли (сложный / нестандартный) способ сделать это?

Было бы что-то вроде

 $stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN (?, ?, ?, ?);
  

работает? Итак, если бы я хотел выполнить поиск по переменному количеству идентификаторов, мог бы я сделать

 $ids = array(1,2,3,4,5,6,7);
$idSection = implode(array_pad(array(), count($ids), '?')) //To give ?,?,?,?,?,?,?
$stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN ($idSection);
$stmp->execute($ids);
  

Даже если бы это сработало, это все равно не очень полезно для запуска нескольких наборов данных с одним и тем же подготовленным оператором, если только искомый набор $ids не имеет одинаковой длины каждый раз и не работает с заполнителями имен.

Я предполагаю, что если вы сделаете

 $stmt = $db->prepare( 'SELECT title FROM episode WHERE id IN (:ids);
$ids = implode('","' array(1,2,3,4,5,6,7));
$stmt->bindParam( ':ids', $ids);
  

Сбой, потому что подготовленный оператор был сконструирован так, что он будет искать единственное значение id и «1»,»2″,»3″,»4″,»5″,»6″,»7″ не соответствует?

Я уверен, что есть лучший ответ, чем просто не использовать IN(...) предложения. Должен ли я просто очистить $ids термин вручную и включить его в запрос без заполнителей?

 $stmt = $db->prepare( "SELECT title FROM episode WHERE id IN $ids AND genre like :genre");
$stmt->bindParam( ':genre', '%$genre%);
  

Ответ №1:

В MySQL есть функция FIND_IN_SET, которую вы можете использовать для достижения того же результата:

 $ids = array(1,2,3,4,5,6,7);
$stmt = $db->prepare( 'SELECT title FROM episode WHERE FIND_IN_SET(id,?)' );
$param = implode(',',$ids);
$stmt->bind_param('s',$param); 
$stmt->execute(); 
  

Комментарии:

1. И помните, FIND_IN_SET работает очень медленно по сравнению с предложением IN

Ответ №2:

Способ избежать использования IN-предложений — заполнить временную таблицу значениями, которые будут входить в IN ( … ) в виде списка, разделенного запятыми; затем либо ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ в столбце временной таблицы, либо выполнение вложенного выбора:

         inner join temptable T2 on T1.mycol = T2.col1
  

или

        ...  where mycol in ( Select col1 from temptable)
  

Комментарии:

1. Это хорошая идея! Но поскольку я пытаюсь делать все «подготовленным способом», то мне либо приходится запускать подготовленную инструкцию с несколькими вставками для построения временной таблицы (которая сталкивается с проблемой того же типа), либо запускать подготовленную инструкцию с одной вставкой несколько раз. Я знаю, что многократное выполнение подготовленной одиночной вставки должно быть быстрее, чем многократное выполнение обычной одиночной вставки, но все равно будет ли это значительно медленнее, чем многократная вставка?

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