【问题标题】:How can I get an error when running multiple queries with PDO?使用 PDO 运行多个查询时如何出现错误?
【发布时间】:2014-04-23 14:35:09
【问题描述】:

我正在使用 PDO 运行多个查询。如果第二个查询失败,则不会抛出异常。

$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$sql = "
DELETE FROM car; 
INSERT INTO car(name, type) SELECT name, from FROM vehicle;
";

try {
    $db->exec($sql);
}
catch (PDOException $e)
{
    echo $e->getMessage();
    die();
}

上面的代码执行没有抛出异常。

如何确保所有查询都已成功运行?如何检查哪些查询失败?

附注我正在使用 PDO 多查询来运行 MySQL 转储,但是任何有效的 .sql 文件都应该可以工作。

【问题讨论】:

  • 最好的方法是一次运行一个。此外,您的 INSERT 查询中存在 SQL 语法错误 - SELECT 语句在 name, 之后需要另一个列名
  • @Kryten 我正在使用 PDO 运行 MySQL 转储。拆分转储是一项艰巨的任务。示例中的错误是故意的。
  • 啊,我明白了。在这种情况下,我唯一的建议是检查您的 catch 块中的 PDOException 并查看它是否包含有关失败的特定查询的更多详细信息。从 catch 块中的 print_r($e) 开始...
  • 在 catch 块中放置 print_r($db->errorInfo()); 会起作用吗?
  • 问题是没有抛出PDOException。

标签: php mysql pdo


【解决方案1】:

我在使用准备好的语句中找到了答案。遍历所有行集后,我可以使用$stmt->errorInfo() 检查执行的最后一个查询是否导致错误。

$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);

$sql = "
DELETE FROM car; 
INSERT INTO car(name, type) SELECT name, from FROM vehicle;
";

$stmt = $db->prepare($sql);
$stmt->execute();
$i = 0;

do {
  $i++;
} while ($stmt->nextRowset());

$error = $stmt->errorInfo();
if ($error[0] != "00000") {
  echo "Query $i failed: " . $error[2];
  die();
}

【讨论】:

  • 在您的解决方案中,如果出现不正确的语句,请执行任何其他语句,但此(此链接:stackoverflow.com/questions/6346674/…)解决方案可帮助您一起运行多个语句,如果出现不正确的语句,则不会执行任何其他语句
【解决方案2】:

以下代码将展示如何在运行多个查询时捕获错误。尽量避免使用“DELIMITER //”。查询一般用“;”分开。

<?php
// Create SQL List
$sqlStatements = "SELECT 100;SELECT 200;SELECT 300; Error SELECT 400;SELECT 500;";

// Prepare and execute statements
$options = [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION];
$db = new PDO("mysql:host=127.0.0.1;dbname=test", 'root', '', $options);

// Prepare and execute
$error = false;
$statement = $db->prepare($sqlStatements);
$statement->execute();

// Check error
try{
    do{
        // Print Resultset
        $rowset = $statement->fetchAll(PDO::FETCH_NUM);
        var_dump($rowset);
    }while($statement->nextRowset());

}catch(\Exception $e){
    echo $e->getMessage()."\n";
}
?>

【讨论】:

    【解决方案3】:

    没有明确而简单的方法可以做到这一点。

    我认为,最好的方法是逐个查询读取转储文件并一次执行一个查询。

    如果数据库驱动程序告诉它,您还可以解析错误消息并提取问题行号(如'unknown identifier 'blabla'on line 666')。

    【讨论】:

    • 那会让我从火里跳到煎锅里。查询很可能有“;”在他们的价值观中。另外我不想把重点放在转储文件的格式上。任何有效的 .sql 文件都应该这样做。
    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 2021-06-12
    • 2020-05-25
    相关资源
    最近更新 更多