
Andru
Ich bin neugierig zu wissen, ob es möglich ist, ein Array von Werten mit PDO an einen Platzhalter zu binden. Der Anwendungsfall hier versucht, ein Array von Werten zur Verwendung mit an zu übergeben IN()
Zustand.
Ich würde gerne in der Lage sein, so etwas zu tun:
<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>
Und lassen Sie PDO alle Werte im Array binden und zitieren.
Im Moment mache ich:
<?php
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
foreach($ids as &$val)
$val=$db->quote($val); //iterate through array and quote
$in = implode(',',$ids); //create comma separated list
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN('.$in.')'
);
$stmt->execute();
?>
Was sicherlich den Job macht, aber ich frage mich nur, ob es eine eingebaute Lösung gibt, die ich vermisse?

stefs
Sie müssen die Abfragezeichenfolge konstruieren.
<?php
$ids = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids), '?'));
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(' . $inQuery . ')'
);
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
?>
Sowohl Chris (Kommentare) als auch Someoneisintrouble schlugen vor, dass die Foreach-Schleife …
(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
… könnte überflüssig sein, so die foreach
Schleife und die $stmt->execute
könnte einfach ersetzt werden durch …
<?php
(...)
$stmt->execute($ids);

uɥƃnɐʌuop
Für was schnelles:
//$db = new PDO(...);
//$ids = array(...);
$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)");
$sth->execute($ids);

Tim Tonkonogow
Ist es so wichtig zu verwenden IN
Aussage? Versuchen zu benutzen FIND_IN_SET
op.
Zum Beispiel gibt es eine solche Abfrage in PDO
SELECT * FROM table WHERE FIND_IN_SET(id, :array)
Dann müssen Sie nur ein Array von Werten binden, die mit Kommas implodiert sind, wie dieses hier
$ids_string = implode(',', $array_of_smth); // WITHOUT WHITESPACES BEFORE AND AFTER THE COMMA
$stmt->bindParam('array', $ids_string);
und fertig.
UPD: Wie einige Leute in Kommentaren zu dieser Antwort darauf hingewiesen haben, gibt es einige Probleme, die ausdrücklich erwähnt werden sollten.
FIND_IN_SET
verwendet keinen Index in einer Tabelle und ist noch nicht implementiert – siehe diesen Eintrag im MYSQL-Bugtracker. Danke an @BillKarwin für den Hinweis.
- Sie können keine Zeichenfolge mit Komma als Wert des Arrays für die Suche verwenden. Es ist unmöglich, eine solche Zeichenfolge danach richtig zu analysieren
implode
da Sie das Komma-Symbol als Trennzeichen verwenden. Danke an @VaL für den Hinweis.
Kurz gesagt, wenn Sie nicht stark von Indizes abhängig sind und keine Zeichenfolgen mit Komma für die Suche verwenden, ist meine Lösung viel einfacher, einfacher und schneller als die oben aufgeführten Lösungen.
Da ich viele dynamische Abfragen mache, ist dies eine supereinfache Hilfsfunktion, die ich erstellt habe.
public static function bindParamArray($prefix, $values, &$bindArray)
{
$str = "";
foreach($values as $index => $value){
$str .= ":".$prefix.$index.",";
$bindArray[$prefix.$index] = $value;
}
return rtrim($str,",");
}
Verwenden Sie es wie folgt:
$bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray);
$userConditions .= " AND users.id IN($bindString)";
Gibt eine Zeichenfolge zurück :id1,:id2,:id3
und aktualisiert auch Ihre $bindArray
von Bindungen, die Sie benötigen, wenn es an der Zeit ist, Ihre Abfrage auszuführen. Leicht!
Ein sehr sauberer Weg für Postgres ist die Verwendung des Postgres-Arrays (“{}”):
$ids = array(1,4,7,9,45);
$param = "{".implode(', ',$ids)."}";
$cmd = $db->prepare("SELECT * FROM table WHERE id = ANY (?)");
$result = $cmd->execute(array($param));
Die Lösung von EvilRygy hat bei mir nicht funktioniert. In Postgres können Sie eine andere Problemumgehung durchführen:
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id = ANY (string_to_array(:an_array, ','))'
);
$stmt->bindParam(':an_array', implode(',', $ids));
$stmt->execute();
Hier ist meine Lösung:
$total_items = count($array_of_items);
$question_marks = array_fill(0, $total_items, '?');
$sql="SELECT * FROM foo WHERE bar IN (" . implode(',', $question_marks ). ')';
$stmt = $dbh->prepare($sql);
$stmt->execute(array_values($array_of_items));
Beachten Sie die Verwendung von array_values. Dadurch können Probleme bei der Schlüsselbestellung behoben werden.
Ich habe Arrays von IDs zusammengeführt und dann doppelte Elemente entfernt. Ich hatte so etwas wie:
$ids = array(0 => 23, 1 => 47, 3 => 17);
Und das scheiterte.
10055200cookie-checkKann ich ein Array an eine IN()-Bedingung in einer PDO-Abfrage binden?yes
Eine vollständige Anleitung zum Binden eines Arrays an eine IN()-Bedingungeinschließlich des Falls, wenn Sie andere Platzhalter in der Abfrage haben
– Ihr gesunder Menschenverstand
18. April 2017 um 14:10 Uhr
Die Frage wurde als Duplikat dieser Frage geschlossen. Ich habe das Duplikat-Flag umgekehrt, weil diese Frage 4 Jahre älter ist, 4-mal so viele Aufrufe, 3-mal so viele Antworten und 12-mal so viele Punkte hat. Es ist eindeutig das übergeordnete Ziel.
– Mike32
7. März 2020 um 1:58 Uhr
Wer sich das 2020 anschaut: Man könnte es versuchen github.com/morris/dop dafür.
– Morris4
9. Mai 2020 um 16:55 Uhr