Les procédures stockées

La base de donnĂ©es MySQL supporte les procĂ©dures stockĂ©es. Une procĂ©dure stockĂ©e est une sous routine stockĂ©e dans le catalogue de la base de donnĂ©es. Les applications peuvent appeler et exĂ©cuter une procĂ©dure stockĂ©e. La requĂȘte SQL CALL est utilisĂ©e pour exĂ©cuter une procĂ©dure stockĂ©e.

ParamĂštre

Les procédures stockées peuvent avoir des paramÚtres IN, INOUT et OUT, suivant la version de MySQL. L'interface mysqli n'a pas de notion spécifique des différents types de paramÚtres.

ParamĂštre IN

Les paramĂštres d'entrĂ©e sont fournis avec la requĂȘte CALL. Il faut s'assurer d'Ă©chapper correctement les valeurs.

Exemple #1 Appel d'une procédure stockée

<?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)");

$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;");

$mysqli->query("CALL p(1)");

$result = $mysqli->query("SELECT id FROM test");

var_dump($result->fetch_assoc());

L'exemple ci-dessus va afficher :

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

ParamĂštre INOUT/OUT

Les valeurs des paramÚtres INOUT/OUT sont accédées en utilisant les variables de session.

Exemple #2 Utilisation des variables de session

<?php

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

$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;');

$mysqli->query("SET @msg = ''");
$mysqli->query("CALL p(@msg)");

$result = $mysqli->query("SELECT @msg as _p_out");

$row = $result->fetch_assoc();
echo
$row['_p_out'];

L'exemple ci-dessus va afficher :

Hi!

Les développeurs d'application et de framework peuvent fournir une API plus conviviale utilisant un mix des variables de session et une inspection du catalogue de la base de données. Cependant, veuillez garder à l'esprit l'impact sur les performances dû à une solution personnalisée basée sur l'inspection du catalogue.

Gestion des jeux de résultats

Les procĂ©dures stockĂ©es peuvent retourner des jeux de rĂ©sultats. Les jeux de rĂ©sultats retournĂ©s depuis une procĂ©dure stockĂ©e ne peuvent ĂȘtre rĂ©cupĂ©rĂ©s correctement en utilisant la fonction mysqli::query(). La fonction mysqli::query() combine l'exĂ©cution de la requĂȘte et la rĂ©cupĂ©ration du premier jeu de rĂ©sultats dans un jeu de rĂ©sultats mis en mĂ©moire tampon, s'il y en a. Cependant, il existe d'autres jeux de rĂ©sultats issus de la procĂ©dure stockĂ©e qui sont cachĂ©s de l'utilisateur et qui font que la fonction mysqli::query() Ă©choue lors de la rĂ©cupĂ©ration des jeux de rĂ©sultats attendus de l'utilisateur.

Les jeux de rĂ©sultats retournĂ©s depuis une procĂ©dure stockĂ©e sont rĂ©cupĂ©rĂ©s en utilisant la fonction mysqli::real_query() ou mysqli::multi_query(). Ces deux fonctions autorisent la rĂ©cupĂ©ration de n'importe quel nombre de jeux de rĂ©sultats retournĂ©s par une requĂȘte, comme la requĂȘte CALL. L'Ă©chec dans la rĂ©cupĂ©ration de tous les jeux de rĂ©sultats retournĂ©s par une procĂ©dure stockĂ©e cause une erreur.

Exemple #3 Récupération des résultats issus d'une procédure stockée

<?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)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');

$mysqli->multi_query("CALL p()");

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

L'exemple ci-dessus va afficher :

---
array(3) {
  [0]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  [1]=>
  array(1) {
    [0]=>
    string(1) "2"
  }
  [2]=>
  array(1) {
    [0]=>
    string(1) "3"
  }
}
---
array(3) {
  [0]=>
  array(1) {
    [0]=>
    string(1) "2"
  }
  [1]=>
  array(1) {
    [0]=>
    string(1) "3"
  }
  [2]=>
  array(1) {
    [0]=>
    string(1) "4"
  }
}

Utilisation des requĂȘtes prĂ©parĂ©es

Aucune gestion spĂ©ciale n'est requise lors de l'utilisation de l'interface de prĂ©paration des requĂȘtes pour rĂ©cupĂ©rer les rĂ©sultats depuis la mĂȘme procĂ©dure stockĂ©e que celle ci-dessous. Les interfaces de requĂȘte prĂ©parĂ©e et non prĂ©parĂ©e sont similaires. Veuillez noter que toutes les versions du serveur MySQL ne supportent pas la prĂ©paration des requĂȘtes SQL CALL.

Exemple #4 ProcĂ©dures stockĂ©es et requĂȘte prĂ©parĂ©e

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
if (
$mysqli->connect_errno) {
echo
"Échec lors de la connexion à MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');

$stmt = $mysqli->prepare("CALL p()");

if (!
$stmt->execute()) {
echo
"Échec lors de l'exĂ©cution : (" . $stmt->errno . ") " . $stmt->error;
}

do {
if (
$result = $stmt->get_result()) {
var_dump($result->fetch_all());
$result->free();
}
} while (
$stmt->next_result());

L'exemple ci-dessus va afficher :

---
array(3) {
  [0]=>
  array(1) {
    [0]=>
    int(1)
  }
  [1]=>
  array(1) {
    [0]=>
    int(2)
  }
  [2]=>
  array(1) {
    [0]=>
    int(3)
  }
}
---
array(3) {
  [0]=>
  array(1) {
    [0]=>
    int(2)
  }
  [1]=>
  array(1) {
    [0]=>
    int(3)
  }
  [2]=>
  array(1) {
    [0]=>
    int(4)
  }
}

Bien sûr, l'utilisation de l'API de liage pour la récupération est également supportée.

Exemple #5 ProcĂ©dures stockĂ©es et requĂȘte prĂ©parĂ©e en utilisant l'API de liage

<?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)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');

$stmt = $mysqli->prepare("CALL p()");

$stmt->execute();

do {
if (
$stmt->store_result()) {
$stmt->bind_result($id_out);
while (
$stmt->fetch()) {
echo
"id = $id_out\n";
}
}
} while (
$stmt->next_result());

L'exemple ci-dessus va afficher :

id = 1
id = 2
id = 3
id = 2
id = 3
id = 4

Voir aussi

add a note

User Contributed Notes 1 note

up
2
Valverde ¶
6 years ago
<?php

// Store procedure call without params

$MyConnection = new mysqli ("DB_SERVER", "DB_USER", "DB_PASS", "DB_NAME");

mysqli_multi_query ($MyConnection, "CALL MyStoreProcedure") OR DIE (mysqli_error($MyConnection));

while (mysqli_more_results($MyConnection)) {

       if ($result = mysqli_store_result($MyConnection)) {

              while ($row = mysqli_fetch_assoc($result)) {

                     // i.e.: DBTableFieldName="userID"
                     echo "row = ".$row["DBTableFieldName"]."<br />";
                     ....

              }
              mysqli_free_result($result);
       }
       mysqli_next_result($conn);

}
?>
*******************************************************************
<?php

// Store procedure call using params

$MyConnection = new mysqli ("DB_SERVER", "DB_USER", "DB_PASS", "DB_NAME");

mysqli_query($MyConnection ,"SET @p0='".$MyParam1."'");
mysqli_query($MyConnection ,"SET @p1='".$MyParam2."'");
mysqli_multi_query ($MyConnection, "CALL MyStoreProcedure (@p0,@p1)") OR DIE (mysqli_error($MyConnection));

while (mysqli_more_results($MyConnection)) {

       if ($result = mysqli_store_result($MyConnection)) {

              while ($row = mysqli_fetch_assoc($result)) {

                     // i.e.: DBTableFieldName="userID"
                     echo "row = ".$row["DBTableFieldName"]."<br />";
                     ....

              }
              mysqli_free_result($result);
       }
       mysqli_next_result($conn);

}
?>