php – 当PDO :: exec()中的任何语句失败时,有没有办法抛出异常?

PDO::exec()允许(至少对某些驱动程序,如mysqlnd)一次执行多个语句.

这很好用,当我向PDO :: exec()传递几个查询时,它们都会被执行:

$pdo->exec('DROP TABLE a; DROP TABLE b;');

我的PDO实例配置为抛出异常:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

如果第一个查询失败,则会按预期引发异常:

$pdo->exec('DROP TABLE does_not_exist; DROP TABLE ok;'); // PDOException

但是当任何后续查询失败时,它会默默地忽略这个事实而你似乎没有办法知道它:

$pdo->exec('DROP TABLE ok; DROP TABLE does_not_exist;'); // no exception
var_export($pdo->errorInfo()); // array (0 => '00000', 1 => NULL, 2 => NULL)

有没有办法配置PDO,以便exec()在任何语句失败时抛出异常?

请注意,我目前没有明显更好的选择在自己的exec()调用中运行每个查询,因为我正在编写一个读取SQL转储文件的工具.

最佳答案
有趣的问题……我相信(如果我错了,请纠正我)这个“多个”exec会在每个exec之后调用每个exec …所以一旦你得到异常,就会返回它并停止执行你的查询.

用例:
(dbname)测试包含2个表’a’和’b’

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

echo "BEFORE:<br/>";
foreach($db->query("show tables;") as $row) echo $row[0] . "<br />";

$a = $db->exec("drop table b; drop table c");

echo "AFTER:<br/>";
foreach($db->query("show tables;") as $row) echo $row[0] . "<br />";

在这里我得到结果:

BEFORE:
a
b
AFTER:
a
1              <--- ^.^

这在某种程度上是愚蠢的.但可能正确的解决方案是使用PDO交易.如果某些代码失败,您应该能够还原更改.基本上,如果你开始交易,你将在每次查询后关闭自动提交(最后提到的3个查询除外!!!).还原或提交将再次启用自动提交.

尝试代替$db-> exec(“q1; q2; q3”)……这样的事情:

try {
    $db->beginTransaction();
    $db->exec("drop table b;");           // -- note at the end of post!
    $db->exec("drop table c;");
    $db->commit();
} catch (PDOException $e) {
    print_r($e);
    $db->rollBack();
}

基本上这种方法是有效的.然而!

请注意,您不能使用TRUNCATE TABLE,因为此语句将触发提交,就像CREATE TABLE或DROP TABLE一样.

因此,如果您正在处理像DROP TABLE等的查询…在这种特殊情况下,您的正确解决方案是使用此查询而不是简单的drop:

SQL: DROP TABLE IF EXISTS `tablename`;

此语句不会触发异常;)

希望它有所帮助^.^

转载注明原文:php – 当PDO :: exec()中的任何语句失败时,有没有办法抛出异常? - 代码日志