mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 08:58:56 +00:00
209 lines
6.2 KiB
XML
209 lines
6.2 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
|
|
<chapter xml:id="pdo.prepared-statements" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Prepared statements and stored procedures</title>
|
|
<para>
|
|
Many of the more mature databases support the concept of prepared
|
|
statements. What are they? They can be thought of as a kind of compiled
|
|
template for the SQL that an application wants to run, that can be customized
|
|
using variable parameters. Prepared statements offer two major benefits:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
The query only needs to be parsed (or prepared) once, but can be
|
|
executed multiple times with the same or different parameters. When the
|
|
query is prepared, the database will analyze, compile and optimize its
|
|
plan for executing the query. For complex queries this process can take
|
|
up enough time that it will noticeably slow down an application if there
|
|
is a need to repeat the same query many times with different parameters. By
|
|
using a prepared statement the application avoids repeating the
|
|
analyze/compile/optimize cycle. This means that prepared statements use fewer
|
|
resources and thus run faster.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
The parameters to prepared statements don't need to be quoted; the
|
|
driver automatically handles this. If an application exclusively uses
|
|
prepared statements, the developer can be sure that no SQL injection will
|
|
occur (however, if other portions of the query are being built up with
|
|
unescaped input, SQL injection is still possible).
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
Prepared statements are so useful that they are the only feature that PDO
|
|
will emulate for drivers that don't support them. This ensures that an
|
|
application will be able to use the same data access paradigm regardless of
|
|
the capabilities of the database.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Repeated inserts using prepared statements</title>
|
|
<simpara>
|
|
This example performs an INSERT query by substituting a <literal>name</literal>
|
|
and a <literal>value</literal> for the named placeholders.
|
|
</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);
|
|
|
|
// insert one row
|
|
$name = 'one';
|
|
$value = 1;
|
|
$stmt->execute();
|
|
|
|
// insert another row with different values
|
|
$name = 'two';
|
|
$value = 2;
|
|
$stmt->execute();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Repeated inserts using prepared statements</title>
|
|
<simpara>
|
|
This example performs an INSERT query by substituting a <literal>name</literal>
|
|
and a <literal>value</literal> for the positional <literal>?</literal> placeholders.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
|
|
$stmt->bindParam(1, $name);
|
|
$stmt->bindParam(2, $value);
|
|
|
|
// insert one row
|
|
$name = 'one';
|
|
$value = 1;
|
|
$stmt->execute();
|
|
|
|
// insert another row with different values
|
|
$name = 'two';
|
|
$value = 2;
|
|
$stmt->execute();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Fetching data using prepared statements</title>
|
|
<simpara>
|
|
This example fetches data based on a key value supplied by a form.
|
|
The user input is automatically quoted, so there is no risk of a
|
|
SQL injection attack.
|
|
</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>Calling a stored procedure with an output parameter</title>
|
|
<simpara>
|
|
If the database driver supports it, an application may also bind parameters for
|
|
output as well as input. Output parameters are typically used to retrieve
|
|
values from stored procedures. Output parameters are slightly more complex
|
|
to use than input parameters, in that a developer must know how large a given
|
|
parameter might be when they bind it. If the value turns out to be larger
|
|
than the size they suggested, an error is raised.
|
|
</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
|
|
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000);
|
|
|
|
// call the stored procedure
|
|
$stmt->execute();
|
|
|
|
print "procedure returned $return_value\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Calling a stored procedure with an input/output parameter</title>
|
|
<simpara>
|
|
Developers may also specify parameters that hold values both input and output;
|
|
the syntax is similar to output parameters. In this next example, the
|
|
string 'hello' is passed into the stored procedure, and when it returns,
|
|
hello is replaced with the return value of the procedure.
|
|
</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);
|
|
|
|
// call the stored procedure
|
|
$stmt->execute();
|
|
|
|
print "procedure returned $value\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Invalid use of placeholder</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
|
|
$stmt->execute([$_GET['name']]);
|
|
|
|
// placeholder must be used in the place of the whole value
|
|
$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
|
|
-->
|
|
|