Gespeicherte Prozeduren (Stored Procedures)
  
   Die MySQL-Datenbank unterstützt gespeicherte Prozeduren. Eine gespeicherte
   Prozedur ist ein Unterprogramm, das im Datenbankkatalog gespeichert ist.
   Anwendungen können die gespeicherte Prozedur aufrufen und ausführen. Um
   eine gespeicherte Prozedur auszuführen, wird die SQL-Anweisung
   CALL verwendet.
  
  
   Parameter
  
  
   In Abhängigkeit von der MySQL-Version können gespeicherte Prozeduren die
   Parameter IN, INOUT und
   OUT haben. Die mysqli-Schnittstelle selbst hat keine
   speziellen Bezeichnungen für die verschiedenen Arten von Parametern.
  
  
   Der Parameter IN
  
  
   Die Eingabeparameter werden mit der Anweisung
   CALL bereitgestellt. Bitte stellen Sie sicher, dass die
   Werte korrekt maskiert sind.
  
  
   
    Beispiel #1 Aufrufen einer gespeicherten Prozedur
    
<?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());
     
    Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
array(1) {
  ["id"]=>
  string(1) "1"
}
 
    
  
  
   Die Parameter INOUT/OUT
  
  
   Auf die Werte der Parameter INOUT/OUT
   wird über Session-Variablen zugegriffen.
  
  
   
    Beispiel #2 Verwendung von Session-Variablen
    
<?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'];
     
    Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
 
  
  
   Anwendungs- und Framework-Entwickler können gegebenenfalls eine
   komfortablere API bereitstellen, die neben Session-Variablen auch das
   direkte Durchsuchen von Datenbankkatalogen verwendet. Dabei sind jedoch die
   Leistungseinbußen zu beachten, die eine benutzerdefinierte Lösung auf Basis
   der Kataloginspektion haben kann.
  
  
   Umgang mit Ergebnismengen
  
  
   Gespeicherte Prozeduren können Ergebnismengen zurückgeben. Ergebnismengen,
   die von einer gespeicherten Prozedur zurückgegeben werden, können mit
   mysqli::query() nicht korrekt abgerufen werden. Die
   Funktion mysqli::query() führt die Anweisung aus
   und ruft, falls vorhanden, die erste Ergebnismenge in einen Puffer ab.
   Gespeicherte Prozeduren können jedoch weitere Ergebnismengen zurückgeben,
   die dem Benutzer verborgen sind, was dazu führt, dass
   mysqli::query() nicht die vom Benutzer erwarteten
   Ergebnismengen zurückgibt.
  
  
   Ergebnismengen, die von einer gespeicherten Prozedur zurückgegeben werden,
   werden mit mysqli::real_query() oder
   mysqli::multi_query() abgerufen. Beide Funktionen
   ermöglichen das Abrufen einer beliebigen Anzahl von Ergebnismengen, die
   von einer Anweisung wie CALL zurückgegeben werden.
   Gelingt es nicht, alle Ergebnismengen abzurufen, die von einer
   gespeicherten Prozedur zurückgegeben wurden, löst das einen Fehler aus.
  
  
   
    Beispiel #3 Ergebnisse von gespeicherten Prozeduren abrufen
    
<?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 ($result = $mysqli->store_result()) {
        printf("---\n");
        var_dump($result->fetch_all());
        $result->free();
    }
} while ($mysqli->next_result());
     
    Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
---
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"
  }
}
 
    
  
  
   Verwendung von vorbereiteten Anweisungen
  
  
   Es ist keine besondere Vorgehensweise erforderlich, wenn die Schnittstelle
   für vorbereitete Anweisungen zum Abrufen von Ergebnissen aus der gleichen
   gespeicherten Prozedur wie oben verwendet wird. Die Schnittstellen für
   vorbereitete und nicht-vorbereitete Anweisungen sind ähnlich. Es ist zu
   beachten, dass nicht jede Version des MYSQL-Servers die Vorbereitung der
   SQL-Anweisung CALL unterstützt.
  
  
   
    Beispiel #4 Gespeicherte Prozeduren und vorbereitete Anweisungen
    
<?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 ($result = $stmt->get_result()) {
        printf("---\n");
        var_dump($result->fetch_all());
        $result->free();
    }
} while ($stmt->next_result());
     
    Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
---
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)
  }
}
 
    
  
  
   Natürlich wird auch die Verwendung der bind-API für das Abrufen von Daten
   unterstützt.
  
  
   
    Beispiel #5 Gespeicherte Prozeduren und vorbereitete Anweisungen mit der bind-API
    
<?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());
     
    Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
id = 1
id = 2
id = 3
id = 2
id = 3
id = 4
 
    
  
  
   Siehe auch