Instrucciones predefinidas

El concepto básico de instrucción predefinida es enviar a MySQL, por una parte una plantilla con la consulta que queremos ejecutar y por otras los datos. Esto puede resultarnos útil a la hora de ejecutar varias consultas iguales, como por ejemplo inserciones o borrados en bloque, además de ayudarnos a prevenir ataques de inyección SQL. Además son muy útiles para acelerar la ejecución cuando se ejecutan varias consultas iguales con diferentes datos. Por último destacar que tienen un funcionamiento similar a los PreparedStatement de JDBC del lenguaje JAVA.

Veamos un ejemplo de inserción con la metodología orientada a procedimientos:

<?php
$db = mysqli_connect('localhost', 'comprador', 'proweb2013', 'uazon');

// Definimos la plantilla de la consulta.
$consulta =
   "INSERT INTO libros(isbn, titulo,n_pags,precio,fk_editoriales) " .
   " VALUES(?, ?, ?, ?, ?)";

 // Inicializamos la sentencia preparada.
$stmt = mysqli_stmt_init($db);

//preparamos la consulta
if (mysqli_stmt_prepare($stmt, $consulta) !== false) {
   $isbn = 123456789;
   $titulo = 'Zen to Done';
   $n_pags = 150;
   $precio = 10.99;
   $fk_editoriales = 8; //foreig key -> EDITORIALES (Alfaguara)

   // Asociamos parametros a la plantilla
   mysqli_stmt_bind_param($stmt, "isiii", $isbn, $titulo,
      $n_pags, $precio, $fk_editoriales);

   mysqli_stmt_execute($stmt);

   echo mysqli_stmt_affected_rows($stmt).' libro insertado.';
   // Finalizamos el uso de la plantilla
   mysqli_stmt_close($stmt);
}
mysqli_close($db);
?>

Ejemplo de inserción con la metodología orientada a objetos:

<?php
$db = new mysqli('localhost', 'comprador', 'proweb2013', 'uazon');

// Definimos la plantilla de la consulta.
$consulta =
   "INSERT INTO libros(isbn,titulo,n_pags,precio,fk_editoriales) ".
   " VALUES(?, ?, ?, ?, ?)";

// Instanciamos la plantilla.
$stmt = $db->stmt_init();

if ($stmt->prepare($consulta) !== false) {
   $isbn = 123456789;
   $titulo = 'Zen to Done';
   $n_pags = 150;
   $precio = 10.99;
   $fk_editoriales = 8; //foreign key -> EDITORIALES (Alfaguara)

   // Asociamos parametros a la plantilla
   $stmt->bind_param("isiii",
         $isbn,$titulo,$n_pags,$precio,$fk_editoriales);

   $stmt->execute();
   echo $stmt->affected_rows.' libro insertado.';
   // Finalizamos el uso de la plantilla
   $stmt->close();
}
$db->close();
?>

Veamos el ejemplo más detenidamente.

En primer lugar creamos la sentencia preparada con mysqli_stmt_init o $db->stmt_init().

**Procedimientos:**

mysqli_stmt mysqli_stmt_init ( mysqli $identificador_de_enlace)

Ejemplo:

// Inicializamos la sentencia preparada.
$stmt = mysqli_stmt_init ($db);

**Objetos:**

class mysqli {
   mysqli_stmt stmt_init ( void )
}

En nuestro ejemplo:

// Inicializamos la sentencia preparada.
$stmt = $db->stmt_init();

Lo importante de esta función y método es que devuelven una instancia de la clase MySQLI_STMT que representa una sentencia preparada. Más información en el manual de PHP: http://www.php.net/manual/es/class.mysqli-stmt.php

En segundo lugar preparamos la consulta comprobando que es correcta. En el ejemplo tenemos la siguiente consulta:

// Definimos la plantilla de la consulta.
$consulta = "INSERT INTO libros (isbn, titulo,n_pags,precio,fk_editoriales) " .
   " VALUES(?, ?, ?, ?, ?)";

La consulta que le pasamos puede incluir uno o más marcadores de parámetro, insertando el carácter interrogativo (?) en la posición apropiada.

Los marcadores sólo son válidos en la lista VALUES() de una sentencia INSERT, o en una comparación en una cláusula WHERE. Sin embargo, no son permitidos para identificadores (tales como nombres de tabla o columna), en el listado de los nombres de las columnas a ser devueltas por la sentencia SELECT, o para especificar operadores.

Veamos como preparar la instrucción predefinida:

**Procedimientos:**

bool mysqli_stmt_prepare ( mysqli_stmt $stmt, string $consulta)

Ejemplo:

// Preparamos la consulta
if (mysqli_stmt_prepare($stmt, $consulta) !== false)
{

**Objetos:**

class mysqli_stmt {
   mixed prepare ( string $consulta )
}

En nuestro ejemplo:

// Preparamos la consulta
if ($stmt->prepare($consulta) !== false)
{

El tercer paso será asociar las variables a la plantilla, de tal manera que las variables deben coincidir con los marcadores de (?) que pusimos en la misma. Para eso utilizaremos:

**Procedimientos:**

bool mysqli_stmt_bind_param( mysqli_stmt $stmt, string $tipos,
   mixed &$var1 [, mixed &$... ] )

Ejemplo:

// Asociamos parametros a la plantilla
mysqli_stmt_bind_param($stmt, "isiii", $isbn, $titulo,
   $n_pags, $precio, $fk_editoriales);

**Objetos:**

class mysqli_stmt {
   mixed bind_param ( string $tipos, mixed &$var1 [, mixed &$... ] )
}

En nuestro ejemplo:

// Asociamos parametros a la plantilla
$stmt->bind_param("isiii", $isbn, $titulo, $n_pags, $precio, $fk_editoriales);

Tanto la función como el método reciben una cadena de formato similar a la de printf donde se especificará el número y los tipos de las variables que van a ir a continuación.

En nuestro ejemplo pasamos la cadena "**isiis**", donde indicamos que hay cinco parámetros, el primero entero ("i" de integer), el segundo cadena ("s" de string), el tercero y cuarto enteros y el último cadena.

En la tabla que aparece a continuación podemos ver los diferentes tipos de parámetros que podemos usar dentro de una sentencia preparada.

Diferentes opciones para definir un parámetro en la plantilla de una sentencia preparada
Carácter Descripción
i La variable correspondiente tiene tipo entero
d La variable correspondiente tiene tipo doble
s La variable correspondiente tiene tipo string
b La variable correspondiente tiene tipo BLOB y será enviada en paquetes

A continuación pasaremos las variables coincidiendo en número y tipo con el formato.

Una vez hecha la asociación(bind) podremos ejecutar la sentencia, para ello utilizaremos:

**Procedimientos:**

bool mysqli_stmt_execute ( mysqli_stmt $stmt )

Ejemplo:

// Ejecutamos instrucción
mysqli_stmt_execute ($stmt);

**Objetos:**

class mysqli_stmt {
   mixed execute ( void )
}

En nuestro ejemplo:

// Ejecutamos instrucción
$stmt->execute();

Devuelven TRUE o FALSE en caso de éxito o error respectivamente.

Como es un INSERT podremos consultar el número de filas insertadas. Utilizaremos:

**Procedimientos:**

int mysqli_stmt_affected_rows ( mysqli_stmt $stmt )

Ejemplo:

printf("Libros insertados: %d\n", mysqli_stmt_affected_rows($stmt));

**Objetos:**

class mysqli_stmt {
   int affected_rows
}

En nuestro ejemplo:

echo $stmt->affected_rows.' libro insertado.';

Este proceso de bind y execute puede estar en un bucle si vamos a realizar más de una inserción.

Por último debemos liberar el manejador de sentencias, cancelando cualquier resultado pendiente con las siguientes instrucciones:

**Procedimientos:**

bool mysqli_stmt_close ( mysqli_stmt $stmt )

Ejemplo:

mysqli_stmt_close($stmt);

**Objetos:**

class mysqli_stmt {
   bool stmt_close ( void )
}

En nuestro ejemplo:

$stmt->close();

Como vemos en el ejemplo también podremos hacerlo usando objetos con un proceso idéntico.

Si lo que deseamos es obtener resultados con un SELECT tras el stmt_execute deberemos obtenerlos con mysqli_stmt_bind_result y después usar mysqli_stmt_fetch para obtener los valores. Para profundizar más en este tema se recomienda visitar este enlace: http://php.net/manual/es/function.mysqli-stmt-bind-result.php

<?php
$db = new mysqli('localhost', 'comprador', 'proweb2013', 'uazon');

$descripcion = " %". addslashes('guerra')." %";

$query = "SELECT titulo FROM libros where titulo like ?";

$stmt = $db->stmt_init();

if ($stmt->prepare($query) !== false) {
   $stmt->bind_param("s", $descripcion);

   $stmt->execute();

   $stmt->store_result(); //averiguar el numero de filas

   echo $stmt->num_rows . ' libros encontrados.<br>';
   $stmt->bind_result($titulo);

   while ($stmt->fetch()) {
      echo stripslashes($titulo) . "<br>";
   }
   $stmt->free_result();

   $stmt->close();
}
$db->close();
?>

results matching ""

    No results matching ""