PDO-Unterstützung für mehrere Abfragen (PDO_MYSQL, PDO_MYSQLND)

Lesezeit: 12 Minuten

PDO Unterstutzung fur mehrere Abfragen PDO MYSQL PDO MYSQLND
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.

  • 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

1647060850 585 PDO Unterstutzung fur mehrere Abfragen PDO MYSQL PDO MYSQLND
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.

  • An der Antwort selbst ist nichts auszusetzen. Es erklärt, wie mehrere Abfragen ausgeführt werden. Ihre Annahme, dass die Antwort fehlerhaft ist, beruht auf der Annahme, dass die Abfrage Benutzereingaben enthält. Es gibt gültige Anwendungsfälle, in denen das gleichzeitige Senden mehrerer Abfragen die Leistung verbessern kann. Sie könnten vorschlagen, Prozeduren als alternative Antwort auf diese Frage zu verwenden, aber das macht diese Antwort nicht schlecht.

    – Gajus

    21. April 2014 um 11:53 Uhr

  • Der Code in dieser Antwort ist schlecht und fördert einige sehr schädliche Praktiken (Verwendung von Emulation für Prepares-Anweisungen, die Code offen für SQL-Injection-Schwachstelle). Benutze es nicht.

    – teresko

    24. April 2014 um 19:32 Uhr


  • An dieser Antwort und insbesondere am Emulationsmodus ist nichts auszusetzen. Es ist standardmäßig in pdo_mysql aktiviert, und wenn es ein Problem gäbe, gäbe es bereits Tausende von Injektionen. Aber noch niemand hat sich einem genähert. Also geht es.

    – Ihr gesunder Menschenverstand

    24. April 2014 um 20:06 Uhr

  • Tatsächlich war ircmaxell nur einer, der es schaffte, nicht nur Emotionen, sondern auch Argumente zu bieten. Links, die er mitgebracht hat, sind jedoch ziemlich irrelevant. Das erste ist überhaupt nicht anwendbar, wie es ausdrücklich gesagt wird “PDO ist immer immun gegen diesen Fehler.” Während der zweite einfach lösbar ist, indem die richtige Codierung eingestellt wird. Es verdient also eine Anmerkung, keine Warnung und eine weniger ansprechende.

    – Ihr gesunder Menschenverstand

    28. April 2014 um 8:45 Uhr


  • Als jemand, der ein Migrationstool schreibt, das SQL verwendet, das nur unsere Entwickler geschrieben haben (dh SQL-Injection ist kein Problem), hat mir dies massiv geholfen, und alle Kommentare, die darauf hinweisen, dass dieser Code schädlich ist, verstehen nicht alles vollständig Kontexte für seine Verwendung.

    – Lukas

    6. April 2016 um 9:20 Uhr

1647060851 23 PDO Unterstutzung fur mehrere Abfragen PDO MYSQL PDO MYSQLND
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>";
}

  • Funktioniert es wenn man nur läuft $pdo->exec("valid-stmt1; non-sense; valid-stmt3;"); ohne die beiden vorherigen execs? Ich kann es dazu bringen, Fehler in der Mitte zu werfen, aber nicht, wenn es ausgeführt wird nach dem erfolgreiche Führungskräfte.

    – Jeff Puckett

    18. Oktober 2016 um 20:08 Uhr

  • Nein, tut es nicht. Das ist der Fehler bei PDO.

    – Sai Phaninder Reddy J

    19. Oktober 2016 um 1:08 Uhr

  • Meine Güte, diese 3 $pdo->exec("") sind voneinander unabhängig. Ich habe sie jetzt aufgeteilt, um anzuzeigen, dass sie nicht in einer Reihenfolge sein müssen, damit das Problem auftritt. Diese 3 sind 3 Konfigurationen zum Ausführen mehrerer Abfragen in einer exec-Anweisung.

    – Sai Phaninder Reddy J

    19. Oktober 2016 um 1:24 Uhr

  • Interessant. Konnten Sie meine gepostete Frage sehen? Ich frage mich, ob dies teilweise gepatcht wurde, weil ich den Fehler auslösen kann, wenn es der einzige ist exec auf der Seite, aber wenn ich mehrere laufe exec jeweils mit mehreren SQL-Anweisungen darin, dann reproduziere ich hier denselben Fehler. Aber wenn es das einzige ist exec auf der Seite, dann kann ich es nicht reproduzieren.

    – Jeff Puckett

    19. Oktober 2016 um 2:43 Uhr

  • Habe das gemacht exec auf Ihrer Seite mehrere Aussagen haben?

    – Sai Phaninder Reddy J

    19. Oktober 2016 um 22:16 Uhr

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.

  • Dies schlägt fehl, wenn Ihre SQL-Datei eingebaute mysql-Befehle enthält … Es wird wahrscheinlich auch Ihr PHP-Speicherlimit sprengen, wenn die SQL-Datei groß ist … Splitting on ; bricht ab, wenn Ihr SQL Prozedur- oder Trigger-Definitionen enthält … Viele Gründe, warum es nicht gut ist.

    – Bill Karwin

    19. Oktober 2016 um 1:41 Uhr

PDO Unterstutzung fur mehrere Abfragen PDO MYSQL PDO MYSQLND
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 DELETEdann 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…

  • Sie hätten es zu einer neuen Frage machen sollen, wenn Sie sich auf diese beziehen

    – Ihr gesunder Menschenverstand

    30. April 2014 um 17:07 Uhr


  • Nicht so viel Frage als Ergebnis dessen, was ich versucht habe. Und mein Fazit. Ursprüngliche Frage ist alt, möglicherweise im Moment nicht aktuell.

    – Andrés

    30. April 2014 um 17:13 Uhr


  • Ich bin mir nicht sicher, wie dies für irgendetwas in der Frage relevant ist.

    – chao

    17. Juni 2014 um 3:08 Uhr

  • fraglich sind Wörter but you risk to be injected with multiple queries. Meine Antwort bezieht sich auf die Injektion

    – Andrés

    20. Januar 2015 um 13:30 Uhr


PDO Unterstutzung fur mehrere Abfragen PDO MYSQL PDO MYSQLND
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();
}

  • Sie hätten es zu einer neuen Frage machen sollen, wenn Sie sich auf diese beziehen

    – Ihr gesunder Menschenverstand

    30. April 2014 um 17:07 Uhr


  • Nicht so viel Frage als Ergebnis dessen, was ich versucht habe. Und mein Fazit. Ursprüngliche Frage ist alt, möglicherweise im Moment nicht aktuell.

    – Andrés

    30. April 2014 um 17:13 Uhr


  • Ich bin mir nicht sicher, wie dies für irgendetwas in der Frage relevant ist.

    – chao

    17. Juni 2014 um 3:08 Uhr

  • fraglich sind Wörter but you risk to be injected with multiple queries. Meine Antwort bezieht sich auf die Injektion

    – Andrés

    20. Januar 2015 um 13:30 Uhr


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());

  • Ich würde diese Art von Argumentation nie verstehen: “Hier ist ein Code, der eine große Lücke in der Sicherheit darstellt und alle empfohlenen bewährten Verfahren vernachlässigt, also müssen Sie über die Auswirkungen auf die Sicherheit nachdenken.” Wer soll daran denken? Wann sollten sie nachdenken – bevor sie diesen Code verwenden oder nachdem sie gehackt wurden? Warum denken Sie nicht zuerst darüber nach, bevor Sie diese Funktion schreiben oder anderen anbieten?

    – Ihr gesunder Menschenverstand

    9. Juli 2020 um 3:04 Uhr


  • Sehr geehrter @YourCommonSense, mehrere Abfragen auf einmal auszuführen, hilft bei der Leistung, weniger Netzwerkverkehr + Server kann verwandte Abfragen optimieren. Mein (vereinfachtes) Beispiel sollte nur die Methode vorstellen, die zu seiner Verwendung erforderlich ist. Es ist nur dann eine Sicherheitslücke, wenn Sie die bewährten Praktiken, auf die Sie sich beziehen, nicht anwenden. Übrigens bin ich misstrauisch gegenüber Leuten, die sagen “Ich würde nie verstehen …”, wenn sie es leicht könnten … 🙂

    – Andrés

    10. Juli 2020 um 20:22 Uhr

992720cookie-checkPDO-Unterstützung für mehrere Abfragen (PDO_MYSQL, PDO_MYSQLND)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy