/MySQLi, bind_param und NOT IN()
ChrisB
- php
Hi,
ich moechte bei einer Selektion ueber die MySQLi-Erweiterung in einer Query ueber die WHERE-Klausel Datensaetze mit bestimmten IDs ausschliessen.
Die IDs habe ich in einem PHP-Array vorliegen.
$excludeIDs = array(1, 2, 5, 4711);
$excludeIDsImploded = implode(', ', $excludeIDs); // liefert mir also '1, 2, 5, 4711'
Jetzt moechte ich das in einer Query in der WHERE-Klausel mit NOT IN nutzen, habe also
$STMT = $mysqli->stmt_init();
$STMT->prepare('SELECT ... FROM ... WHERE id NOT IN(?)');
echo $STMT->error;
$STMT->bind_param('s', $excludeIDsImploded);
echo $STMT->error;
$STMT->execute();
echo $STMT->error;
Bekomme keine Fehlermeldungen, aber beim fetchen der Datensaetze dann auch die jenigen mit den IDs, die eigentlich per WHERE NOT IN() ausgeschlossen werden sollten, zurueckgegeben.
Also ist wohl meine Vorgehensweise, das Textliteral mit dem Inhalt '1, 2, 5, 4711' per bind_param() als Inhalt fuer NOT IN(?) einsetzen zu wollen, nicht korrekt. Da kommt wohl, wenn man mal etwas genauer drueber nachdenkt, effektiv sowas wie NOT IN('1, 2, 5, 4711') bei heraus.
Wie wuerde man sowas korrekt machen?
Oder geht das mit der MySQLi-Erweiterung und Prepared Statements gar nicht?
(MySQL-Version ist 4.1.22, PHP 5.2.5)
MfG ChrisB
Hi,
ein "Workaround" waere dann wohl,
$STMT->prepare(sprintf('SELECT ... FROM ... WHERE id NOT IN(%s)', $excludeIDsImploded));
zu verwenden.
Dann komme ich zwar ohne $STMT->bind_params() aus - aber "sauber" kommt mir das nicht vor.
Wozu denn dann ueberhaupt noch Prepared Statements nutzen, dann kann ich ja gleich den "alten" Weg ueber mysql_query gehen ...?
MfG ChrisB
echo $begrüßung;
ein "Workaround" waere dann wohl,
$STMT->prepare(sprintf('SELECT ... FROM ... WHERE id NOT IN(%s)', $excludeIDsImploded));
zu verwenden.
Ein anderer Workaround wäre, die Anzahl der Fragezeichen der Anzahl der Werte anzupassen.
$sql = sprintf('… NOT IN (%s)', implode(',', array_fill(0, count($excludeIDs), '?')));
Desweiteren braucht man einen zweiten Kopfstand, um die variable Anzahl der Werte an das Statement zu binden: </archiv/2008/2/t167140/#m1090087>
Dann komme ich zwar ohne $STMT->bind_params() aus - aber "sauber" kommt mir das nicht vor.
Aus Sicht eines Datenbänkers könnte eine Antwort lauten: Korrigiere dein Datenlayout, so dass du mit JOINs arbeiten kannst. Wenn das nicht geht (vielleicht weil die Werte aus einer vom Anwender zu erstellenden Kreuzchenliste kommen), dann wirst du wohl einen der Workarounds nehmen müssen.
echo "$verabschiedung $name";
Hi,
Ein anderer Workaround wäre, die Anzahl der Fragezeichen der Anzahl der Werte anzupassen.
$sql = sprintf('… NOT IN (%s)', implode(',', array_fill(0, count($excludeIDs), '?')));
Desweiteren braucht man einen zweiten Kopfstand, um die variable Anzahl der Werte an das Statement zu binden: </archiv/2008/2/t167140/#m1090087>
Na, das wird mir dann zu umstaendlich - dann feuere ich doch lieber direkt mit mysqli->query eine selbst zusammengebastelte Abfrage ab.
Dann komme ich zwar ohne $STMT->bind_params() aus - aber "sauber" kommt mir das nicht vor.
Aus Sicht eines Datenbänkers könnte eine Antwort lauten: Korrigiere dein Datenlayout, so dass du mit JOINs arbeiten kannst. Wenn das nicht geht (vielleicht weil die Werte aus einer vom Anwender zu erstellenden Kreuzchenliste kommen), dann wirst du wohl einen der Workarounds nehmen müssen.
Ich moechte zusaetzlich zu ein paar Datensaetze, die auf einer Seite mittels bestimmter Auswahlkriterien angezeigt werden, zusaetzlich noch ein paar weitere, zufaellig ausgeaehlte anzeigen - ohne dabei "Doppelte" zu bekommen.
MfG ChrisB
echo $begrüßung;
Ich moechte zusaetzlich zu ein paar Datensaetze, die auf einer Seite mittels bestimmter Auswahlkriterien angezeigt werden, zusaetzlich noch ein paar weitere, zufaellig ausgeaehlte anzeigen - ohne dabei "Doppelte" zu bekommen.
Nun, dann könnte man die erste Anfrage (die Ergebnisfeldliste gekürzt auf die ID) als Subselect im IN(…) der zweiten wiederholen.
echo "$verabschiedung $name";
Hi,
Nun, dann könnte man die erste Anfrage (die Ergebnisfeldliste gekürzt auf die ID) als Subselect im IN(…) der zweiten wiederholen.
OK, das waere fuer dieses Szenario eine Moeglichkeit.
Aber spaetestens dann, wenn ich nach einer Zufallsabfrage dann noch mal weitere Datensaetze ermitteln wollte, die auch wieder keinen der vorherigen enthalten sollen, haut das auch nicht mehr hin.
Ich glaub' ich bastel mir doch die Query direkt, und schick sie "altmodisch" ab.
MfG ChrisB