mirror of
https://github.com/php/doc-es.git
synced 2026-03-23 23:12:09 +01:00
214 lines
6.7 KiB
XML
214 lines
6.7 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<!-- EN-Revision: 84e8f0960b841a5ebca9d81cd2c2311b6504a371 Maintainer: PhilDaiguille Status: ready -->
|
|
<!-- Reviewed: yes -->
|
|
|
|
<chapter xml:id="pdo.prepared-statements" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Consultas preparadas y procedimientos almacenados</title>
|
|
<para>
|
|
La mayoría de las bases de datos soportan el concepto de consultas preparadas.
|
|
¿Qué son? Pueden verse como una especie de plantilla compilada
|
|
para el SQL que se desea ejecutar, que puede ser personalizada utilizando
|
|
variables como parámetros. Las consultas preparadas ofrecen
|
|
dos funcionalidades esenciales:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
La consulta solo debe ser analizada (o preparada) una vez, pero puede
|
|
ser ejecutada múltiples veces con parámetros idénticos o diferentes.
|
|
Cuando la consulta es preparada, la base de datos analizará, compilará
|
|
y optimizará su plan para ejecutar la consulta. Para consultas complejas,
|
|
este proceso puede tomar bastante tiempo, lo que puede ralentizar las aplicaciones
|
|
si se debe repetir la misma consulta múltiples veces con diferentes parámetros.
|
|
Al utilizar consultas preparadas, se evita repetir el ciclo análisis/compilación/optimización. En resumen, las consultas preparadas
|
|
utilizan menos recursos y se ejecutan más rápidamente.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Los parámetros para preparar las consultas no necesitan estar entre
|
|
comillas; el controlador gestiona esto. Si la aplicación utiliza exclusivamente
|
|
consultas preparadas, se puede estar seguro de que no es posible ninguna
|
|
inyección SQL (Sin embargo, si se construyen otras partes de la consulta
|
|
basándose en entradas de usuario, se sigue asumiendo un riesgo).
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
Las consultas preparadas son tan prácticas que es la única funcionalidad
|
|
que PDO emula para los controladores que no las soportan. Esto asegura poder
|
|
utilizar la misma técnica para acceder a los datos, sin preocuparse por las capacidades
|
|
de la base de datos.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Inserciones repetitivas utilizando consultas preparadas</title>
|
|
<simpara>
|
|
Este ejemplo realiza una consulta INSERT sustituyendo un
|
|
<literal>nombre</literal> y un <literal>valor</literal> para los marcadores nombrados.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
|
|
$stmt->bindParam(':name', $name);
|
|
$stmt->bindParam(':value', $value);
|
|
|
|
// inserción de una fila
|
|
$name = 'one';
|
|
$value = 1;
|
|
$stmt->execute();
|
|
|
|
// inserción de otra fila con valores diferentes
|
|
$name = 'two';
|
|
$value = 2;
|
|
$stmt->execute();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Inserciones repetidas utilizando consultas preparadas</title>
|
|
<simpara>
|
|
Este ejemplo realiza una consulta INSERT sustituyendo un <literal>nombre</literal>
|
|
y un <literal>valor</literal> para los marcadores <literal>?</literal>.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
|
|
$stmt->bindParam(1, $name);
|
|
$stmt->bindParam(2, $value);
|
|
|
|
// inserción de una fila
|
|
$name = 'one';
|
|
$value = 1;
|
|
$stmt->execute();
|
|
|
|
// inserción de otra fila con diferentes valores
|
|
$name = 'two';
|
|
$value = 2;
|
|
$stmt->execute();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Recuperación de datos utilizando consultas preparadas</title>
|
|
<simpara>
|
|
Este ejemplo recupera datos basados en el valor de una clave proporcionada
|
|
por un formulario. La entrada del usuario es automáticamente escapada, por lo que
|
|
no hay riesgo de ataque por inyección SQL.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
|
|
$stmt->execute([$_GET['name']]);
|
|
foreach ($stmt as $row) {
|
|
print_r($row);
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Llamada a un procedimiento almacenado con un parámetro de salida</title>
|
|
<simpara>
|
|
Si el controlador de la base de datos lo soporta, también se pueden vincular
|
|
parámetros tanto para entrada como para salida. Los parámetros de salida
|
|
se utilizan típicamente para recuperar valores de un procedimiento almacenado.
|
|
Los parámetros de salida son un poco más complejos de usar que los parámetros de entrada
|
|
ya que se debe conocer la longitud que un parámetro dado podrá alcanzar cuando se vincule. Si el valor devuelto es más largo que el tamaño sugerido,
|
|
se emitirá un error.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
|
|
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000);
|
|
|
|
// Llamada al procedimiento almacenado
|
|
$stmt->execute();
|
|
|
|
print "El procedimiento ha devuelto: $return_value\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Llamada a un procedimiento almacenado con un parámetro de entrada/salida</title>
|
|
<simpara>
|
|
También se deben especificar los parámetros que gestionan valores
|
|
tanto para entrada como para salida; la sintaxis es similar a los
|
|
parámetros de salida. En el siguiente ejemplo, la cadena 'Hola' es pasada
|
|
al procedimiento almacenado y cuando devuelve el valor, 'Hola' es reemplazada
|
|
por el valor devuelto por el procedimiento.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
|
|
$value = 'hello';
|
|
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
|
|
|
|
// llamada al procedimiento almacenado
|
|
$stmt->execute();
|
|
|
|
print "El procedimiento ha devuelto: $value\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Uso inválido de marcador</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
|
|
$stmt->execute([$_GET['name']]);
|
|
|
|
// un marcador debe ser utilizado en lugar de un valor completo
|
|
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
|
|
$stmt->execute(["%$_GET[name]%"]);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|