Welche Bedeutung hat das Fragezeichen in MySQL bei “WHERE column =?”?

Ich seze etwas Code und stieß auf dieses,

$sql = 'SELECT page.*, author.name AS author, updator.name AS updator ' . 'FROM '.TABLE_PREFIX.'page AS page ' . 'LEFT JOIN '.TABLE_PREFIX.'user AS author ON author.id = page.created_by_id ' . 'LEFT JOIN '.TABLE_PREFIX.'user AS updator ON updator.id = page.updated_by_id ' . 'WHERE slug = ? AND parent_id = ? AND (status_id='.Page::STATUS_REVIEWED.' OR status_id='.Page::STATUS_PUBLISHED.' OR status_id='.Page::STATUS_HIDDEN.')'; 

Ich frage mich, was das “?” tut es in der WHERE-statement. Ist es eine Art Parameterhalter?

Vorbereitete statementen verwenden das ‘?’ in MySQL, um verbindliche Parameter für die statement zu ermöglichen. Hoch angesehen als sicherer gegen SQL-Injektionen, wenn sie richtig verwendet werden. Dies ermöglicht auch schnellere SQL-Abfragen, da die Anfrage nur einmal kompiliert werden muss und wiederverwendet werden kann.

Das Fragezeichen steht für einen Parameter, der später ersetzt wird. Die Verwendung parametrisierter Abfragen ist sicherer als das direkte Einbetten der Parameter in die Abfrage.

SQL Server ruft diese parametrisierten Abfragen auf, und Oracle ruft Bind-Variablen auf.

Die Verwendung variiert mit der Sprache, in der Sie die Abfrage ausführen.

Hier ist ein Beispiel, wie es von PHP verwendet wird.

Angenommen, $mysqli ist eine databaseverbindung und people ist eine Tabelle mit 4 Spalten.

 $stmt = $mysqli->prepare("INSERT INTO People VALUES (?, ?, ?, ?)"); $stmt->bind_param('sssd', $firstName, $lastName, $email, $age); 

Das 'sssd' ist ein Flag, das den Rest der Parameter identifiziert, wobei s die Zeichenfolge darstellt und d die Ziffern darstellt.

Keiner

? bedeutet nichts zu MySQL WHERE = Klausel, nur zu mehreren externen Schnittstellen wie PHP stdlib und Web-Frameworks wie Rails.

? ist nur ein Syntaxerrors bei:

 CREATE TABLE t (s CHAR(1)); SELECT * FROM t WHERE s = ?; 

weil es nicht notiert ist, und in:

 INSERT INTO t VALUES ('a'); INSERT INTO t VALUES ("?"); SELECT * FROM t WHERE s = '?'; 

es gibt zurück:

 s ? 

also scheinbar ohne besondere Bedeutung.

Rails Beispiel

In Rails zum Beispiel wird das Fragezeichen durch ein Argument ersetzt, das durch eine Variable der Programmiersprache der Bibliothek (Ruby) gegeben wird, zB:

 Table.where("column = ?", "value") 

und es werden automatisch Argumente angegeben, um Bugs und SQL-Injection zu vermeiden.

 SELECT * FROM Table WHERE column = 'value'; 

Das Zitat würde uns retten im Falle von etwas wie:

 Table.where("column = ?", "; INJECTION") 

MySQL 5.0 vorbereitete statementen

MySQL 5.0 hat die vorbereitete statementsfunktion hinzugefügt, die eine ähnliche Semantik wie das Fragezeichen in Web-Frameworks aufweist.

Beispiel aus der Dokumentation:

 PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; SET @a = 3; SET @b = 4; EXECUTE stmt1 USING @a, @b; 

Ausgabe:

 hypotenuse 5 

Diese entziehen auch Sonderzeichen wie erwartet:

 PREPARE stmt1 FROM 'SELECT ? AS s'; SET @a = "'"; EXECUTE stmt1 USING @a; 

Ausgabe:

 s ' 

Dies sind vorbereitete Aussagen, vorbereitete Aussagen bieten zwei wesentliche Vorteile:

Die Abfrage muss nur einmal analysiert (oder vorbereitet) werden, kann aber mehrfach mit denselben oder anderen Parametern ausgeführt werden. Wenn die Abfrage vorbereitet ist, analysiert, kompiliert und optimiert die database ihren Plan zum Ausführen der Abfrage. Bei komplexen Abfragen kann dieser process so lange dauern, dass eine Anwendung merklich verlangsamt wird, wenn die gleiche Abfrage mehrmals mit unterschiedlichen Parametern wiederholt werden muss. Durch Verwendung einer vorbereiteten statement vermeidet die Anwendung das Wiederholen des Analyse- / Kompilierungs- / Optimierungszyklus. Dies bedeutet, dass vorbereitete statementen weniger Ressourcen verbrauchen und somit schneller ausgeführt werden.

Die Parameter zu vorbereiteten statementen müssen nicht zitiert werden; Der Treiber behandelt dies automatisch. Wenn eine Anwendung ausschließlich vorbereitete statementen verwendet, kann der Entwickler sicher sein, dass keine SQL-Injektion stattfindet (wenn jedoch andere Teile der Abfrage mit nicht deklarierter Eingabe aufgebaut werden, ist SQL-Injektion weiterhin möglich).

http://php.net/manual/de/pdo.prepared-statements.php