2012-08-13 14 views
5

Muszę wybrać kilka wierszy z bazy danych za pomocą operatora IN. Chcę to zrobić za pomocą przygotowanego oświadczenia. To jest mój kod:MySQLi przygotował wyciągi z operatorem IN

<?php 
$lastnames = array('braun', 'piorkowski', 'mason', 'nash'); 
$in_statement = '"' . implode('", "', $lastnames) . '"'; //"braun", "piorkowski", "mason", "nash" 

$data_res = $_DB->prepare('SELECT `id`, `name`, `age` FROM `users` WHERE `lastname` IN (?)'); 
$data_res->bind_param('s', $in_statement); 
$data_res->execute(); 
$result = $data_res->get_result(); 
while ($data = $result->fetch_array(MYSQLI_ASSOC)) { 
    ... 
} 
?> 

Ale nic nie zwraca, mimo że wszystkie dane znajdują się w bazie danych.

I jeszcze jedno: jeśli przekażę $in_statement bezpośrednio do zapytania i wykonam, dane zostaną zwrócone. Problem pojawia się przy przygotowywaniu.

Szukałem pytania w Google, ale nie było to pomyślne. Co jest nie tak z moim kodem?
Dzięki za pomoc!

+3

Nie możesz użyć jednego parametru dla swojej klauzuli IN. Musi to być: 'GDZIE nazwisko last (?,?,?,?)' – andrewsi

+1

OK, wielkie dzięki!) Wydaje się trochę uciążliwe. – kpotehin

Odpowiedz

4

Ostatnio znalazłem rozwiązanie dla mojego pytania. Może to nie jest najlepszy sposób, aby to zrobić, ale działa dobrze! Udowodnij, że się mylę :)

<?php 
$lastnames = array('braun', 'piorkowski', 'mason', 'nash'); 
$arParams = array(); 

foreach($lastnames as $key => $value) //recreate an array with parameters explicitly passing every parameter by reference 
    $arParams[] = &$lastnames[$key]; 

$count_params = count($arParams); 

$int = str_repeat('i',$count_params); //add type for each variable (i,d,s,b); you can also determine type of the variable automatically (is_int, is_float, is_string) in loop, but i don't need it 
array_unshift($arParams,$int); 

$q = array_fill(0,$count_params,'?'); //form string of question marks for statement 
$params = implode(',',$q); 

$data_res = $_DB->prepare('SELECT `id`, `name`, `age` FROM `users` WHERE `lastname` IN ('.$params.')'); 
call_user_func_array(array($data_res, 'bind_param'), $arParams); 
$data_res->execute(); 
$result = $data_res->get_result(); 
while ($data = $result->fetch_array(MYSQLI_ASSOC)) { 
    ... 
} 

$result->free(); 
$data_res->close(); 
?> 
2

Przygotowane oświadczenia mają dokładnie uniknąć tego, co starasz się zrobić to zrobić :)

Aby uzyskać to do pracy trzeba zastosować ten krok:

$escaped_lastnames = join(',', array_map(array($_DB, 'real_escape_string'), $lastnames)); 

mapuje właściwego ciąg funkcja ucieczki dla twojej bazy danych dla każdej pozycji $lastnames. Po zakończeniu wstawia się tę wartość bezpośrednio do zapytania, tj. Bez użycia powiązanych parametrów.

+0

Dzięki, Jack, ale znalazłem sposób na wykonanie tego zapytania za pomocą przygotowanej instrukcji. Używam call_user_func_array (array ($ data_res, 'bind_param'), $ arParams); zamiast zwykłego bind_param. $ arParams zawiera typy zmiennych i tych zmiennych dokładnie) – kpotehin

+0

Po prostu napisałem mój kod jako odpowiedź) – kpotehin

+2

@kpotehin na pewno, jeśli naprawdę musisz (ab) użyć przygotowanych wyciągów do tego, możesz oczywiście :) osobiście nie widzę korzyść, chyba że musi działać kilka razy w ramach jednego wykonania php –