2009-03-23 6 views
38

Je disséquant un code et suis tombé sur ce,Quelle est la signification du point d'interrogation dans MySQL à "WHERE column =?"?

$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.')'; 

Je me demande ce que le « ? » fait dans l'instruction WHERE. Est-ce une sorte de porte-paramètre?

Répondre

35

Les états préparés utilisent le '?' dans MySQL pour autoriser les paramètres de liaison à l'instruction. Hautement considéré comme plus sûr contre les injections SQL s'il est utilisé correctement. Cela permet également des requêtes SQL plus rapides car la requête ne doit être compilée qu'une seule fois et peut être réutilisée.

+0

Comment les utiliser? Je veux dire par là comment définir le point d'interrogation pour prendre un paramètre? – Levi

+1

Il existe plusieurs façons de faire des instructions préparées, PDO et MySQLi les supportent. http://us3.php.net/mysqli http://us3.php.net/manual/fr/mysqli.prepare.php et une recherche rapide sur google m'a amené à http://www.petefreitag.com/item/ 356.cfm – Jayrox

24

Le point d'interrogation représente un paramètre qui sera remplacé ultérieurement. L'utilisation de requêtes paramétrées est plus sûre que l'intégration des paramètres directement dans la requête.

SQL Server appelle cette requête de paramétrage et Oracle l'appelle en associant des variables.

L'utilisation varie selon la langue d'exécution de la requête.

Voici un exemple de la façon dont il est utilisé à partir de PHP.

en supposant que $mysqli est une connexion à une base de données et people est une table à 4 colonnes.

$stmt = $mysqli->prepare("INSERT INTO People VALUES (?, ?, ?, ?)"); 

$stmt->bind_param('sssd', $firstName, $lastName, $email, $age); 

Le 'sssd' est un indicateur identifiant le reste des paramètres, où s représente la chaîne et d représente les chiffres.

1

Ce sont des déclarations préparées, les déclarations préparées offrent deux avantages majeurs:

La requête ne doit être analysé (ou préparé) une fois, mais peut être plusieurs fois exécutés avec les paramètres identiques ou différents. Lorsque la requête est préparée, la base de données analysera, compilera et optimisera son plan d'exécution de la requête. Pour les requêtes complexes, ce processus peut prendre suffisamment de temps pour ralentir sensiblement une application s'il est nécessaire de répéter plusieurs fois la même requête avec des paramètres différents. En utilisant une instruction préparée, l'application évite de répéter le cycle analyser/compiler/optimiser. Cela signifie que les instructions préparées utilisent moins de ressources et s'exécutent donc plus rapidement.

Les paramètres des instructions préparées n'ont pas besoin d'être quotés; le pilote le gère automatiquement. Si une application utilise exclusivement des instructions préparées , le développeur peut être sûr qu'aucune injection SQL ne se produira (cependant, si d'autres parties de la requête sont en cours d'élaboration avec une entrée non échappée, l'injection SQL est toujours possible).

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

5

Aucun

? ne signifie rien à la clause MySQL WHERE =, pour plusieurs interfaces externes tels que les cadres de stdlib et web PHP comme Rails.

? est juste une erreur de syntaxe à:

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

parce qu'elle est non cotée, et:

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

il retourne:

s 
? 

donc apparemment sans signification particulière.

Rails exemple

Dans Rails par exemple, le point d'interrogation est remplacé par un argument donné par une variable de langage de programmation de la bibliothèque (Ruby), par exemple:

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

et automatiquement Citations arguments pour éviter les bogues et injection SQL, la génération d'une déclaration comme:

SELECT * FROM Table WHERE column = 'value'; 

Le citant wo ULD nous sauver en cas de quelque chose comme:

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

MySQL 5.0 instructions préparées

MySQL 5.0 a ajouté le prepared statement feature qui a une sémantique similaire à la marque de question dans les cadres web.

Exemple des docs:

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

Sortie:

hypotenuse 
5 

Ces échapper aussi des caractères spéciaux comme prévu:

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

Sortie:

s 
' 
Questions connexes