
Gajus
Ich weiß, dass PDO nicht mehrere Abfragen unterstützt, die in einer Anweisung ausgeführt werden. Ich habe gegoogelt und einige Beiträge gefunden, in denen es um PDO_MYSQL und PDO_MYSQLND geht.
PDO_MySQL ist eine gefährlichere Anwendung als alle anderen herkömmlichen MySQL-Anwendungen. Herkömmliches MySQL erlaubt nur eine einzige SQL-Abfrage. In PDO_MySQL gibt es keine solche Einschränkung, aber Sie riskieren, mit mehreren Abfragen injiziert zu werden.
Von: Schutz vor SQL-Injection mit PDO und Zend Framework (Juni 2010; von Julian)
Es scheint, als ob PDO_MYSQL und PDO_MYSQLND Unterstützung für mehrere Abfragen bieten, aber ich kann keine weiteren Informationen darüber finden. Wurden diese Projekte eingestellt? Gibt es jetzt eine Möglichkeit, mehrere Abfragen mit PDO auszuführen.

Sam Dunkel
Wie ich weiss, PDO_MYSQLND
ersetzt PDO_MYSQL
in PHP 5.3. Der verwirrende Teil ist, dass der Name immer noch steht PDO_MYSQL
. Jetzt ist ND also der Standardtreiber für MySQL+PDO.
Insgesamt benötigen Sie zum gleichzeitigen Ausführen mehrerer Abfragen Folgendes:
- PHP5.3+
- mysqlnd
- Emulierte vorbereitete Anweisungen. Versicher dich
PDO::ATTR_EMULATE_PREPARES
ist eingestellt auf 1
(Ursprünglich). Alternativ können Sie die Verwendung vorbereiteter Anweisungen vermeiden und verwenden $pdo->exec
direkt.
Verwenden von exec
$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
// works regardless of statements emulation
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
$sql = "
DELETE FROM car;
INSERT INTO car(name, type) VALUES ('car1', 'coupe');
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";
$db->exec($sql);
Anweisungen verwenden
$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
// works not with the following set to 0. You can comment this line as 1 is default
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
$sql = "
DELETE FROM car;
INSERT INTO car(name, type) VALUES ('car1', 'coupe');
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";
$stmt = $db->prepare($sql);
$stmt->execute();
Eine Notiz:
Wenn Sie emulierte vorbereitete Anweisungen verwenden, stellen Sie sicher, dass Sie die richtige Codierung (die die tatsächliche Datencodierung widerspiegelt) in eingestellt haben DSN (verfügbar seit 5.3.6). Andernfalls besteht die Möglichkeit einer SQL-Injection, wenn eine ungewöhnliche Codierung verwendet wird.

Sai Phaninder Reddy J
Nachdem ich einen halben Tag damit herumgespielt hatte, fand ich heraus, dass PDO einen Fehler hatte, wo …
—
//This would run as expected:
$pdo->exec("valid-stmt1; valid-stmt2;");
—
//This would error out, as expected:
$pdo->exec("non-sense; valid-stmt1;");
—
//Here is the bug:
$pdo->exec("valid-stmt1; non-sense; valid-stmt3;");
Es würde die ausführen "valid-stmt1;"
Aufhören "non-sense;"
und niemals einen Fehler werfen. Wird das nicht ausführen "valid-stmt3;"
kehre wahr zurück und lüge, dass alles gut gelaufen ist.
Ich würde erwarten, dass es auf dem Fehler auftritt "non-sense;"
aber das tut es nicht.
Hier habe ich diese Informationen gefunden: Ungültige PDO-Abfrage gibt keinen Fehler zurück
Hier ist der Fehler:
https://bugs.php.net/bug.php?id=61613
Also habe ich versucht, dies mit mysqli zu tun und habe keine wirklich solide Antwort darauf gefunden, wie es funktioniert, also dachte ich, ich lasse es einfach hier für diejenigen, die es verwenden möchten.
try{
// db connection
$mysqli = new mysqli("host", "user" , "password", "database");
if($mysqli->connect_errno){
throw new Exception("Connection Failed: [".$mysqli->connect_errno. "] : ".$mysqli->connect_error );
exit();
}
// read file.
// This file has multiple sql statements.
$file_sql = file_get_contents("filename.sql");
if($file_sql == "null" || empty($file_sql) || strlen($file_sql) <= 0){
throw new Exception("File is empty. I wont run it..");
}
//run the sql file contents through the mysqli's multi_query function.
// here is where it gets complicated...
// if the first query has errors, here is where you get it.
$sqlFileResult = $mysqli->multi_query($file_sql);
// this returns false only if there are errros on first sql statement, it doesn't care about the rest of the sql statements.
$sqlCount = 1;
if( $sqlFileResult == false ){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], [".$mysqli->errno."]: '".$mysqli->error."' }");
}
// so handle the errors on the subsequent statements like this.
// while I have more results. This will start from the second sql statement. The first statement errors are thrown above on the $mysqli->multi_query("SQL"); line
while($mysqli->more_results()){
$sqlCount++;
// load the next result set into mysqli's active buffer. if this fails the $mysqli->error, $mysqli->errno will have appropriate error info.
if($mysqli->next_result() == false){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], Error No: [".$mysqli->errno."]: '".$mysqli->error."' }");
}
}
}
catch(Exception $e){
echo $e->getMessage(). " <pre>".$e->getTraceAsString()."</pre>";
}
Ein Quick-and-Dirty-Ansatz:
function exec_sql_from_file($path, PDO $pdo) {
if (! preg_match_all("/('(\\\\.|.)*?'|[^;])+/s", file_get_contents($path), $m))
return;
foreach ($m[0] as $sql) {
if (strlen(trim($sql)))
$pdo->exec($sql);
}
}
Teilt an sinnvollen Endpunkten von SQL-Anweisungen. Es gibt keine Fehlerprüfung, keinen Injektionsschutz. Verstehen Sie Ihre Verwendung, bevor Sie es verwenden. Ich persönlich verwende es zum Seeding von Migrationsrohdateien für Integrationstests.

Sajad Mirzaei
Wie Tausende von Menschen suche ich nach dieser Frage:
Kann mehrere Abfragen gleichzeitig ausführen, und wenn es einen Fehler gab, wurde keiner ausgeführt. Ich bin überall auf diese Seite gegangen
Aber obwohl die Freunde hier gute Antworten gegeben haben, waren diese Antworten nicht gut für mein Problem
Also habe ich eine Funktion geschrieben, die gut funktioniert und fast keine Probleme mit SQL Injection hat.
Es könnte für diejenigen hilfreich sein, die nach ähnlichen Fragen suchen, also stelle ich sie hier zur Verfügung
function arrayOfQuerys($arrayQuery)
{
$mx = true;
$conn->beginTransaction();
try {
foreach ($arrayQuery AS $item) {
$stmt = $conn->prepare($item["query"]);
$stmt->execute($item["params"]);
$result = $stmt->rowCount();
if($result == 0)
$mx = false;
}
if($mx == true)
$conn->commit();
else
$conn->rollBack();
} catch (Exception $e) {
$conn->rollBack();
echo "Failed: " . $e->getMessage();
}
return $mx;
}
zur Verwendung (Beispiel):
$arrayQuery = Array(
Array(
"query" => "UPDATE test SET title = ? WHERE test.id = ?",
"params" => Array("aa1", 1)
),
Array(
"query" => "UPDATE test SET title = ? WHERE test.id = ?",
"params" => Array("bb1", 2)
)
);
arrayOfQuerys($arrayQuery);
und meine Verbindung:
try {
$options = array(
//For updates where newvalue = oldvalue PDOStatement::rowCount() returns zero. You can use this:
PDO::MYSQL_ATTR_FOUND_ROWS => true
);
$conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password, $options);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo "Error connecting to SQL Server: " . $e->getMessage();
}
Notiz:
Diese Lösung hilft Ihnen, mehrere Anweisungen zusammen auszuführen,
Wenn eine falsche a-Anweisung auftritt, führt sie keine andere Anweisung aus
Habe folgenden Code versucht
$db = new PDO("mysql:host={$dbhost};dbname={$dbname};charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Dann
try {
$db->query('SET NAMES gbk');
$stmt = $db->prepare('SELECT * FROM 2_1_paidused WHERE NumberRenamed = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));
}
catch (PDOException $e){
echo "DataBase Errorz: " .$e->getMessage() .'<br>';
}
catch (Exception $e) {
echo "General Errorz: ".$e->getMessage() .'<br>';
}
Und bekam
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*' LIMIT 1' at line 1
Falls hinzugefügt $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
nach dem $db = ...
Dann kam eine leere Seite
Wenn stattdessen SELECT
versucht DELETE
dann kam in beiden Fällen ein Fehler wie
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* FROM 2_1_paidused WHERE NumberRenamed = '¿\' OR 1=1 /*' LIMIT 1' at line 1
Also mein Fazit, dass keine Injektion möglich ist…

hassan b.
Probieren Sie diese Funktion aus: mehrere Abfragen und das Einfügen mehrerer Werte.
function employmentStatus($Status) {
$pdo = PDO2::getInstance();
$sql_parts = array();
for($i=0; $i<count($Status); $i++){
$sql_parts[] = "(:userID, :val$i)";
}
$requete = $pdo->dbh->prepare("DELETE FROM employment_status WHERE userid = :userID; INSERT INTO employment_status (userid, status) VALUES ".implode(",", $sql_parts));
$requete->bindParam(":userID", $_SESSION['userID'],PDO::PARAM_INT);
for($i=0; $i<count($Status); $i++){
$requete->bindParam(":val$i", $Status[$i],PDO::PARAM_STR);
}
if ($requete->execute()) {
return true;
}
return $requete->errorInfo();
}
PDO unterstützt dies (Stand 2020). Führen Sie einfach wie gewohnt einen query()-Aufruf für ein PDO-Objekt durch und trennen Sie Abfragen durch ; und dann nextRowset(), um zum nächsten SELECT-Ergebnis zu gehen, wenn Sie mehrere haben. Resultsets haben dieselbe Reihenfolge wie die Abfragen. Denken Sie natürlich an die Auswirkungen auf die Sicherheit – akzeptieren Sie also keine vom Benutzer bereitgestellten Abfragen, verwenden Sie keine Parameter usw. Ich verwende es zum Beispiel mit Abfragen, die durch Code generiert werden.
$statement = $connection->query($query);
do {
$data[] = $statement->fetchAll(PDO::FETCH_ASSOC);
} while ($statement->nextRowset());
9927200cookie-checkPDO-Unterstützung für mehrere Abfragen (PDO_MYSQL, PDO_MYSQLND)yes
Verwenden Sie SQL-Transaktionen.
– teresko
13. Oktober 2013 um 12:27 Uhr
Warum möchten Sie mehrere Abfragen verwenden? Sie werden nicht abgewickelt, es ist genauso, als würden Sie sie nacheinander ausführen. IMHO keine Vorteile, nur Nachteile. Im Falle von SQLInjection erlauben Sie dem Angreifer zu tun, was er will.
– mleko
21. April 2014 um 12:21 Uhr
Es ist jetzt 2020, und PDO unterstützt dies – siehe meine Antwort ganz unten.
– Andrés
8. Juli 2020 um 21:43 Uhr