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 :
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