
Cada vez que se envía una consulta al servidor, éste debe analizarla antes de ejecutarla. Algunas sentencias SQL, como las que insertan valores en una tabla, deben repetirse de forma habitual en un programa. Para acelerar este proceso, MySQL admite consultas preparadas. Estas consultas se almacenan en el servidor listas para ser ejecutadas cuando sea necesario.
Por otra parte existe un riesgo de seguridad muy importante al usar formularios para insertar, consultar, modificar, borrar datos en una base de datos, la "inyección SQL" . Unos de los métodos que se recomiendan para evitar este tipo de ataques es precisamente usar consultas parametrizadas ya que los valores de los parámetros, son transmitidos después, usando un protocolo diferente y no necesitan ser escapados.
Para trabajar con consultas preparadas con la extensión MySQLi de PHP, debes utilizar la clase mysqli_stmt
. Utilizando el método stmt_init
de la clase mysqli
(o la función mysqli_stmt_init
) obtienes un objeto de dicha clase.
$conProyecto = new mysqli('localhost', 'gestor', 'secreto', 'proyecto');
$stmt = $conProyecto->stmt_init();
Los pasos que debes seguir para ejecutar una consulta preparada son:
- Preparar la consulta en el servidor MySQL utilizando el método
prepare
(funciónmysqli_stmt_prepare
). - Ejecutar la consulta, tantas veces como sea necesario, con el método
execute
(funciónmysqli_stmt_execute
). - Una vez que ya no se necesita más, se debe ejecutar el método
close
(funciónmysqli_stmt_close
).
Por ejemplo, para preparar y ejecutar una consulta que inserta un nuevo registro en la tabla familia:
$stmt = $conProyecto->stmt_init();
$stmt->prepare('INSERT INTO familias (cod, nombre) VALUES ("TABLET", "Tablet PC")');
$stmt->execute();
$stmt->close();
$conProyecto->close();
El problema que ya habrás observado, es que de poco sirve preparar una consulta de inserción de datos como la anterior, si los valores que inserta son siempre los mismos. Por este motivo las consultas preparadas admiten parámetros. Para preparar una consulta con parámetros, en lugar de poner los valores debes indicar con un signo de interrogación su posición dentro de la sentencia SQL.
$stmt->prepare('INSERT INTO familias (cod, nombre) VALUES (?, ?)');
Y antes de ejecutar la consulta tienes que utilizar el método bind_param
(o la función mysqli_stmt_bind_param
) para sustituir cada parámetro por su valor. El primer parámetro del método bind_param
es una cadena de texto en la que cada carácter indica el tipo de un parámetro, según la siguiente tabla.
Carácter. | Tipo del parámetro. |
---|---|
i. | Número entero. |
i. | Número real (doble precisión). |
s. | Cadena de texto. |
b. | Contenido en formato binario (BLOB). |
En el caso anterior, si almacenas los valores a insertar en sendas variables, puedes hacer:
$stmt = $conProyecto->stmt_init();
$stmt->prepare('INSERT INTO familias (cod, nombre) VALUES (?, ?)');
$cod_producto = "TABLET";
$nombre_producto = "Tablet PC";
$stmt->bind_param('ss', $cod_producto, $nombre_producto);
$stmt->execute();
$stmt->close();
$conProyecto->close();