2

我有一个从 mysqldump 生成的 sql 转储。该文件包括 mysql-version 特定的注释 (/*!{MySQL version number} {Code} */ )。如果我在此块之后插入 sql 语法错误,PDO 不会触发异常。

php代码

$sql = file_get_contents('FooBar.sql');
$pdo = new \PDO('mysql:host=localhost;dbname=FooBar', 'root');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->exec($sql);

FooBar.sql

/*!40101 SET @Foo='Bar' */;
ERROR
INSERT INTO Foo VALUES ('Bar');

执行此操作不会导致任何异常或错误。如果我删除该/*!40101 SET @Foo='Bar' */;语句,或者将错误移动到队列中,则会引发 PDOException。

4

2 回答 2

3

感谢 hek2mgl 让我走上了正确的道路。

PDO 不支持多个查询。如果您执行包含多个查询的语句,它们会被执行,但 PDO 似乎在执行第一个查询后停止运行。样式注释由 MySql 作为常规查询执行,/*!{MySQL version number} {Code} */之后的任何内容都被 PDO 忽略,即使它由 MySql 执行。

指示的相同错误将由以下查询触发:

SET @Foo='Bar';
ERROR
INSERT INTO Foo VALUES ('Bar');

为了使用 PDO 完成这项工作,我需要拆分语句。

$sql = file_get_contents('FooBar.sql');
$lines = explode(';', $sql);
$pdo = new \PDO('mysql:host=localhost;dbname=FooBar', 'root');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
foreach ($lines as $line) {
    $trimmedLine = trim($line, " \t\n\r\0\x0B");
    if (strlen($trimmedLine) > 0) {
        $pdo->exec($trimmedLine.';');
    }
}

编辑:

另一种解决方案是使用 pdo 准备好的语句。

$sql = file_get_contents('FooBar.sql');
$pdo = new \PDO('mysql:host=localhost;dbname=FooBar', 'root');
$stmt = $pdo->prepare($sql);
$stmt->execute();
do {
    ... Do stuff ...
} while ($stmt->nextRowset());
if ($stmt->errorCode() != '00000') {
    ... Handle error ...
}
于 2013-05-06T07:44:27.487 回答
1

这是因为;在评论的末尾。我现在不知道为什么。将进一步调查...

发现这个错误报告。但是不要指望 char 编码会成为问题,因为我已经调查了使用的网络流量wireshark并且 MySQL 返回了一个语法错误(如预期的那样)。仍然不知道为什么 PDO 不能正确处理这个问题。


一种解决方法是使用Mysqli似乎可以正确处理此问题的方法。以下示例演示了这一点:

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'secret');

$result = $pdo->query('
SELECT 1 AS num;
ERROR
SELECT 1 AS num;
');

if(!$result) {
    var_dump($pdo->errorInfo); // silence ...
}

$mysqli = new Mysqli('localhost', 'root', 'user', 'secret');
$result = $mysqli->query('
SELECT 1 AS num;
ERROR
SELECT 1 AS num;
');

if(!$result) {
    print( $mysqli->error);
    // Output: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ERROR SELECT 1 AS num' at line 2
}
于 2013-05-03T11:43:43.030 回答