PDO::exec

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)

PDO::exec执行 SQL 语句并返回受影响的行数

描述

public PDO::exec(string $statement): int|false

PDO::exec() 在一个函数调用中执行 SQL 语句,返回受语句影响的行数。

PDO::exec() 不会返回 SELECT 语句的结果。对于在程序中只需执行一次的 SELECT 语句,可以考虑使用 PDO::query()。对于需要多次执行的语句,可以使用 PDO::prepare() 准备一个 PDOStatement 对象,并使用 PDOStatement::execute() 执行语句。

参数

statement

要准备和执行的 SQL 语句。

查询中的数据应 正确转义

返回值

PDO::exec() 返回由您发出的 SQL 语句修改或删除的行数。如果未影响任何行,PDO::exec() 返回 0

警告

此函数可能返回布尔值 false,但也可能返回一个非布尔值,该值被评估为 false。请阅读有关 布尔值 的部分以了解更多信息。使用 === 运算符 测试此函数的返回值。

以下示例错误地依赖于 PDO::exec() 的返回值,其中影响 0 行的语句会导致对 die() 的调用

<?php
$db
->exec() or die(print_r($db->errorInfo(), true)); // 错误
?>

错误/异常

如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_WARNING,则发出级别为 E_WARNING 的错误。

如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_EXCEPTION,则抛出 PDOException

示例

示例 #1 发出 DELETE 语句

使用没有 WHERE 子句的 DELETE 语句统计删除的行数。

<?php
$dbh
= new PDO('odbc:sample', 'db2inst1', 'ibmdb2');

/* 从 FRUIT 表中删除所有行 */
$count = $dbh->exec("DELETE FROM fruit");

/* 返回已删除的行数 */
print "已删除 $count 行。\n";
?>

上面的示例将输出

Deleted 1 rows.

参见

添加注释

用户贡献的注释 7 个注释

david at acz dot org
18 年前
此函数不能与任何返回结果的查询一起使用。这包括 SELECT、OPTIMIZE TABLE 等。
soletan at toxa dot de
17 年前
值得在这里注意的是,除了上面文档中给出的提示之外,使用 prepare、bind 和 execute 比多次查询语句提供了更多的好处:性能和安全性!

如果您使用 INSERT INTO ... 将一些二进制数据(例如图像文件)插入数据库,那么它可能会提高解析语句的性能,因为它保持较小(只有几个字节,而图像可能有多个 MiBytes),并且不需要转义/引用文件的二进制数据以成为一个正确的字符串值。

最后,例如,如果您希望获得一个不受 SQL 注入攻击影响的更安全的 PHP 应用程序,您_必须_考虑在每个包含数据的语句(如带有 WHERE 子句的 INSERT 或 SELECT)上使用 prepare/execute。使用 prepare、bind 和 execute 将语句代码与相关数据分开是最佳方法——快速且安全!您甚至不需要转义/引用/格式检查任何数据。
Sbastien
1 年前
请注意,使用 MySQL,您可以使用 INSERT 检测到重复键(1 = INSERT,2 = UPDATE)

<?php

// MySQL 特定的 INSERT UPDATE-like 语法
$sql = <<<SQL
INSERT INTO customers
SET
id =
{$pdo->quote($id)},
name =
{$pdo->quote($name)},
address =
{$pdo->quote($address)}
AS new
ON DUPLICATE KEY UPDATE
name = new.name,
address = new.address
SQL;

$result = $pdo->exec($sql);

if (
$result === 1) {
// 已执行新行的 INSERT
} elseif ($result === 2) {
// 已执行现有行的 UPDATE
}
calin at NOSPAM dot softped dot com
8 年前
PDO::eval() 可能在使用 PDO_DBLIB 和 FreeTDS 时,即使操作成功完成,也会对某些语句(例如 CREATE TABLE)返回 `false`。因此,它不是测试操作状态的可靠方法。

PDO::errorInfo() 可用于测试 SQLSTATE 错误代码是否为 '00000'(成功)和 '01000'(成功并有警告)。

<?php
function execute(PDO $conn, $sql) {
$affected = $conn->exec($sql);
if (
$affected === false) {
$err = $conn->errorInfo();
if (
$err[0] === '00000' || $err[0] === '01000') {
return
true;
}
}
return
$affected;
}
?>

PDO::errorInfo(): https://php.net/manual/en/pdo.errorinfo.php
SQLSTATE 代码列表: http://www-01.ibm.com/support/knowledgecenter/SSGU8G_11.70.0/com.ibm.sqls.doc/ids_sqs_0809.htm
roberto at spadim dot com dot br
17 年前
此函数不执行多查询。
要获取它,请查看 SQLITE_EXEC 注释,那里有一个 pereg 函数可以获取所有查询并执行所有查询,然后返回最后一个查询。
hungry dot rahly at gmail dot com
13 年前
对于那些想要一个像 prepare/execute 一样处理参数的 exec 函数的人。您可以使用另一个函数来模拟它。

<?php
class Real_PDO extends PDO {
public function
execParams($sql, $params) {
$stm = $this->prepare($sql);
$result = false;
if(
$stm && $stm->execute($params) ) {
$result = $stm->rowCount();
while(
$stm->fetch(PDO::FETCH_ASSOC) ) {
}
}
return
$result;
}
}
?>

请记住,如果您要进行大量插入操作,您需要以手动方式进行,因为在执行(插入)多次时,准备语句会加快速度。我使用它以便我可以将所有 SQL 语句放在一个地方,并针对 SQL 注入进行自动安全引用。

如果您想知道 fetch 后的原因,请记住,一些数据库可以从 REMOVE/INSERTS 返回类似 SELECT 的数据。对于 PostgreSQL,您可以让它返回所有实际被删除的记录,或者让插入返回插入/后字段函数和 io 触发器触发后的记录,以提供标准化数据。

<?php
define
("BLAH_INSERT", "INSERT INTO blah (id,data) VALUES(?,?)");
$pdo = new Real_PDO("connect string");
$data = array("1", "2");
$pdo->execParams(BLAH_INSERT, $data);
?>
blah at whatevr dot com
16 年前
您不仅不能将其用于 SELECT 语句,也不能将其用于可能返回行的任何语句。“OPTIMIZE table” 就是这样的例子(返回一些带有优化状态的行)。

如果您这样做,PDO 会因“在其他未缓冲查询处于活动状态时无法执行查询”的错误而锁定。
To Top