此函数不能与任何返回结果的查询一起使用。这包括 SELECT、OPTIMIZE TABLE 等。
(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)
PDO::exec — 执行 SQL 语句并返回受影响的行数
PDO::exec() 在单个函数调用中执行 SQL 语句,并返回该语句影响的行数。
PDO::exec() 不返回 SELECT 语句的结果。对于在程序中只需要执行一次的 SELECT 语句,请考虑使用 PDO::query()。对于需要执行多次的语句,请使用 PDO::prepare() 准备一个 PDOStatement 对象,并使用 PDOStatement::execute() 执行该语句。
PDO::exec() 返回由您发出的 SQL 语句修改或删除的行数。如果没有影响任何行,PDO::exec() 返回 0
。
以下示例错误地依赖于 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.
请注意,使用 MySQL,您可以使用 INSERT 检测到重复键(1 = INSERT,2 = UPDATE)
<?php
// MySQL 特定的 INSERT UPDATE 类语法
$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) {
// 已执行新的行插入
} elseif ($result === 2) {
// 已执行现有行的更新
}
值得注意的是,除了上面文档中给出的提示外,使用 prepare、bind 和 execute 比多次查询语句提供了更多好处:性能和安全性!
如果您使用 INSERT INTO ... 将一些二进制数据(例如图像文件)插入数据库,那么它可能会提高解析语句的性能,因为它保持较小(只有几个字节,而图像可能是几兆字节),并且不需要转义/引用文件的二进制数据以成为正确的字符串值。
最后,例如,如果您想要获得一个不受 SQL 注入攻击影响的更安全的 PHP 应用程序,则_必须_考虑对包含数据的每个语句(如包含 WHERE 子句的 INSERT 或 SELECT)使用 prepare/execute。使用 prepare、bind 和 execute 将语句代码与相关数据分离是最佳方法 - 快速且安全!您甚至不需要转义/引用/格式检查任何数据。
当使用 PDO_DBLIB 和 FreeTDS 时,PDO::eval() 对于某些语句(例如 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
此函数不执行 multi_query
要获取它,请查看 SQLITE_EXEC 注释,那里有一个 pereg 函数可以获取所有查询并依次执行,然后返回最后一个查询的结果。