PHP Prepared Statements (MySQL)

Vorbereitete Statements und gebundene Parameter

Ein vorbereitetes Statement ist ein Feature, das für wiederholtes Ausführen desselben (oder ähnlichen) SQL Statments mit hoher Effizienz gebraucht wird.

Vorbereitete Statements funktionieren grundsätzlich wie folgt:

  1. Vorbereiten: Eine SQL Statementvorlage wird erstellt und an die Datenbank gesendet. Gewisse Werte werden dabei nicht spezifiziert, genannt Parameter (mit „?“ gekennzeichnet). Beispiel: INSERT INTO MyGuests VALUES(?, ?, ?)
  2. Die Datenbank analysiert, kompiliert und führt die Abfrageoptimierung auf der SQL-Anweisungsvorlage aus und speichert das Ergebnis, ohne es auszuführen
  3. Ausführen: Zu einem späteren Zeitpunkt bindet die Anwendung die Werte an die Parameter und die Datenbank führt die Anweisung aus. Die Anwendung kann das Statement so oft ausführen wie sie möchte mit unterschiedelichen Werten

Verglichen mit dem direkten Ausführen von SQL-Anweisungen, haben vorbereitete Anweisungen zwei Hauptvorteile:

  • Vorbereitete Statements reduzieren die Parsing-Zeit, da die Vorbereitung der Query nur einmal durchgeführt wird (obwohl die Anweisung mehrmals ausgeführt wird)
  • Gebundene Parameter minimieren die Bandbreite auf dem Server, da du jedes mal nur die Parameter sendest und nicht die gesammte Abfrage
  • Vorbereitete Statements sind sehr nützlich gegen SQL-Injektionen, da Parameterwerte, die später mit einem anderen Protokoll übertragen werden, nicht korrekt escaped werden müssen.. Wenn die ursprüngliche Anweisungsvorlage nicht von einer externen Eingabe abgeleitet wird, kann die SQL-Injektion nicht auftreten.

Das folgende Beispiel nutzt prepared Statements und gebundene Parameter in MySQL:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);

// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john@example.com";
$stmt->execute();

$firstname = "Mary";
$lastname = "Moe";
$email = "mary@example.com";
$stmt->execute();

echo "New records created successfully";
$stmt->close();
$conn->close();
?>

Codezeilen des obigen Beispiels zur Erläuterung:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
In unserem SQL setzen wie ein Fragezeichen (?) ein wo wir ein Integer, String, Double oder Blob Wert ersetzen wollen.

Dann schau dir die bind_param() Funktion an:
$stmt->bind_param("sss", $firstname, $lastname, $email);
Diess Funktion bindet die Parameter an die SQL Query und sagt der Datenbank was die Paremeter sind. Das „sss“ Argument listet die Datemtypen welche die Paramenter sind. Der Buchstabe s sagt MySQL, dass der Parameter ein String (Zeichenfolge) ist.

Die Argumente können einer dieser vier Typen sein:

  • i – Integer (Ganzzahl)
  • d – Double (Kommazahl)
  • s – String (Zeichenfolge)
  • b – BLOB (Binary Large OBjects)

Wir benötigen einen von diesen für jeden Parameter.

Indem wir MySQL sagen welchen Datentyp zu erwarten ist, minimieren wir das Rosiko einer SQL Injection.

Beachte: Wenn wir Daten aus externen Quellen (wie Benutzereingaben) einfügen möchten, ist es sehr wichtig, dass die Daten bereinigt und validiert werden.