【问题标题】:How to get SQL errors when using multiple statements使用多个语句时如何获取 SQL 错误
【发布时间】:2023-04-11 11:07:01
【问题描述】:

我们使用 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() 也返回 no错误:

$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 在多个语句查询中“停止错误”?

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    是的,有。它在我的 PDO 教程中进行了解释,在 running multiple queries 部分下。

    基本上你需要用

    暂时开启仿真模式
    $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
    

    然后使用常规 query() 方法运行 SQL 转储。然后您将不得不遍历每个查询的结果以捕获错误。由于您的查询似乎没有返回任何数据,因此循环可以像

    一样简单
    do {} while ($stmt->nextRowset());
    

    请注意,您必须为 PDO 启用异常模式才能获得错误查询的错误异常。如果您需要查询中的一些数据,例如插入 id,您可以在花括号内添加必要的命令。

    【讨论】:

    • 确实,这行得通!我不认为这会有任何联系,但显然情况似乎如此。不过,MySQL 的奇怪行为。
    猜你喜欢
    • 2017-08-15
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多