## Requêtes multiples

MySQL autorise optionnellement le fait d'avoir plusieurs requêtes dans une seule chaîne de requête mais nécessite une gestion spéciale.

Les requêtes multiples ou multirequêtes doivent être exécutées avec la fonction mysqli::multi_query(). Les requêtes individuelles dans la chaîne de requête sont séparées par un point virgule. Ensuite, tous les jeux de résultats retournés par l'exécution des requêtes doivent être récupérés.

Le serveur MySQL autorise d'avoir des requêtes qui retournent des jeux de résultats ainsi que des requêtes qui ne retournent aucun jeu de résultats dans la même requête multiple.

Exemple #1 Requêtes multiples

    <?php

    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $mysqli = new mysqli("example.com", "user", "password", "database");

    $mysqli->query("DROP TABLE IF EXISTS test");
    $mysqli->query("CREATE TABLE test(id INT)");

    $sql = "SELECT COUNT(*) AS _num FROM test;
            INSERT INTO test(id) VALUES (1);
            SELECT COUNT(*) AS _num FROM test; ";

    $mysqli->multi_query($sql);

    do {
        if ($result = $mysqli->store_result()) {
            var_dump($result->fetch_all(MYSQLI_ASSOC));
            $result->free();
        }
    } while ($mysqli->next_result());

L'exemple ci-dessus va afficher :

    array(1) {
      [0]=>
      array(1) {
        ["_num"]=>
        string(1) "0"
      }
    }
    array(1) {
      [0]=>
      array(1) {
        ["_num"]=>
        string(1) "1"
      }
    }

D'un point de vue de la sécurité

Les fonctions mysqli::query() et mysqli::real_query() de l'API ne définissent pas de drapeau de connexion nécessaire pour l'activation des multirequêtes sur le serveur. Un appel supplémentaire à l'API est utilisé pour les multirequêtes pour réduire la probabilité d'injection SQL accidentelle. Un attaquant peut tenter d'ajouter des requêtes comme `; DROP DATABASE mysql` ou `; SELECT SLEEP(999)`. Si l'attaquant arrive à ajouter ce genre de SQL dans la chaîne de requête mais que mysqli::multi_query() n'est pas utilisé, le serveur n'exécutera que la première requête, mais pas la seconde représentant la requête SQL malicieuse.

Exemple #2 Injection SQL

    <?php

    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $mysqli = new mysqli("example.com", "user", "password", "database");
    $result = $mysqli->query("SELECT 1; DROP TABLE mysql.user");

L'exemple ci-dessus va afficher :

    PHP Fatal error:  Uncaught mysqli_sql_exception: 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 'DROP TABLE mysql.user' at line 1

Prepared statements

L'utilisation des requêtes multiples avec des requêtes préparées n'est pas supportée.

Voir aussi

- mysqli::query()
- mysqli::multi_query()
- mysqli_result::next-result()
- mysqli_result::more-results()

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open