我们使用 PHP >= 7.2 和 PDO 以及 MySQL 驱动程序在一个 exec() 调用中执行多个 SQL 语句。我们使用这个概念来创建由 PHP 执行的数据库迁移脚本。这些纯 SQL 脚本包含多个 SQL 语句,由我们的 PHP 框架执行,如下所示:
$conn = PDO::conn('mysql:......','user','pw');
$ret = $conn->exec('
DROP VIEW IF EXISTS v_my_view;
CREATE VIEW v_my_view AS SELECT id,name FROM mytable;
');
// $ret now contains 1
if ($ret === FALSE) { // some error handling }
即使对于一个 exec() 调用中的许多语句,这也能正常工作:数据库执行所有语句。
现在,如果 SQL 本身包含错误,(例如语法错误或未知列等),对 exec() 的调用返回与之前 (1) 完全相同的结果,并且 DBH::errorInfo() 返回无错误:
$conn = PDO::conn('mysql:......','user','pw');
$ret = $conn->exec('
DROP VIEW IF EXISTS v_my_view;
-- The following statement creates an SQL error (unknown column):
CREATE VIEW v_my_view AS SELECT id,name_not_known FROM mytable;
');
// $ret still contains 1
var_dump($conn->errorInfo()); // Returns Error Code 0, all fine.
所以看起来 PDO::exec() 确实支持多语句,但没有实现任何错误处理/中止机制。 这似乎也是 MySQL 独有的问题:相同的机制在 PostgreSQL 数据库上运行良好。
有什么方法可以强制 PDO 在多个语句查询上“出错时停止”?
最佳答案
是的,有。它在我的 PDO 教程中有解释,在 running multiple queries 下部分。
基本上你需要暂时打开仿真模式
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
然后使用常规 query() 方法运行您的 SQL 转储。然后您将不得不遍历每个查询的结果以捕获错误。由于您的查询似乎没有返回任何数据,因此循环可以像
一样简单do {} while ($stmt->nextRowset());
请注意,您必须为 PDO 启用异常模式,以便为错误查询获取错误异常。如果您需要查询中的一些数据,例如插入 ID,您可以在花括号内添加必要的命令。
关于php - 使用多个语句时如何获取 SQL 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57994664/