PHP8 PDO::prepare
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PHP 8,PECL pdo >= 0.1.0)
PDO::prepare — 预处理要执行的语句,并返回语句对象
说明
public PDO::prepare(string $query, array $options = []): PDOStatement|false
为 PDOStatement::execute() 方法预处理待执行的 SQL 语句。 语句模板可以包含零个或多个参数占位标记,格式是命名(:name)或问号(?)的形式,当它执行时将用真实数据取代。 在同一个语句模板里,命名形式和问号形式不能同时使用; 只能选择其中一种参数形式。 请用参数形式绑定用户输入的数据,不要直接字符串拼接到查询里。
调用 PDOStatement::execute() 时,每一个值的参数占位标记,名称必须唯一。 除非启用模拟(emulation)模式,同一个语句里无法使用重名的参数。
注意:参数占位符仅能字面上展示完整的数据。 不能是字面的一部分,不能是关键词,不能是标识符,不能是其他任意的范围。 举例说明:不能把多个值绑到单个参数里,然后在 SQL 语句里用 IN() 查询。
如果用不同参数,通过 PDO::prepare() 和 PDOStatement::execute() 多次调用同一个 SQL 语句,将提升应用的性能 —— 驱动可以让客户端/服务器缓存查询和元信息。 同时,调用 PDO::prepare() 和 PDOStatement::execute() 还能阻止 SQL 注入攻击,不需要给参数手动加引号与转义。
如果内置驱动不支持参数,PDO 将模拟出参数的功能; 如果驱动仅仅支持其中一种风格(命名参数和问号参数两种),也会自动重写到另外一种风格。
注意: 用于模拟预准备语句和 重写命名或问号样式参数支持非标准 单引号和双引号的反斜杠转义。这意味着终止 紧跟在反斜杠前面的引号不被识别为反斜杠,这 可能导致参数检测错误,导致预准备语句 执行时失败。解决方法是不使用模拟的准备 这样的 SQL 查询,并避免使用参数样式重写参数 这是驱动程序本身支持的。
自 PHP 7.4.0 起,可以通过两个问号来转义问号。 这意味着 在发送查询到数据库时会转换成 。 ???
参数
query
必须是对目标数据库服务器有效的 SQL 语句模板。
options
数组包含一个或多个 key=>value 键值对,为返回的 PDOStatement 对象设置属性。 常见用法是:设置 为 ,将得到可滚动的光标。 某些驱动有驱动级的选项,在 prepare 时就设置。
PDO::ATTR_CURSOR
PDO::CURSOR_SCROLL
返回值
如果数据库服务器已经成功预处理语句,PDO::prepare() 返回 PDOStatement 对象。 如果数据库服务器无法预处理语句,PDO::prepare() 返回 false 或抛出 PDOException (取决于 错误处理)。
注意:模拟模式下的预处理语句不会和数据库服务器交互,所以 PDO::prepare() 不会检查语句。
错误/异常
如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_WARNING,则发出级别为 E_WARNING 的错误。
如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_EXCEPTION,则抛出 PDOException。
示例
示例 #1 命名参数形式的 SQL 语句模板
<?php
/* 传入数组的值,并执行已预处理的语句 */
$sql = 'SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour';
$sth = $dbh->prepare($sql, [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$sth->execute(['calories' => 150, 'colour' => 'red']);
$red = $sth->fetchAll();
/* Array keys can be prefixed with colons ":" too (optional) */
$sth->execute([':calories' => 175, ':colour' => 'yellow']);
$yellow = $sth->fetchAll();
?>
示例 #2 问号形式的 SQL 语句模板
<?php
/* 传入数组的值,并执行已预处理的语句 */
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute([150, 'red']);
$red = $sth->fetchAll();
$sth->execute([175, 'yellow']);
$yellow = $sth->fetchAll();
?>
示例 #3 问号转义的 SQL 语句模板
<?php
/* note: this is only valid on PostgreSQL databases */
$sth = $dbh->prepare('SELECT * FROM issues WHERE tag::jsonb ?? ?');
$sth->execute(['feature']);
$featureIssues = $sth->fetchAll();
$sth->execute(['performance']);
$performanceIssues = $sth->fetchAll();
?>
参见
- PDO::exec() - 执行 SQL 语句,并返回受影响的行数
- PDO::query() - 预处理并执行没有占位符的 SQL 语句
- PDOStatement::execute() - 执行预处理语句