执行多个查询时如何让 PDO 引发异常?
如果我自己运行错误的 sql:
$execute($ddl_partial);
$execute($insert);
然后我得到预期的错误:
PHP 致命错误:未捕获的 PDOException:SQLSTATE[42S22]:找不到列:207 [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]列名“其他”无效。(SQLExecute[207] 在 /build/php7.0-41GaEn/php7.0-7.0.8/ext/pdo_odbc/odbc_stmt.c:260)
但是,如果我先运行一些好的 SQL,然后再用坏的 SQL,它就会吞下错误,一切看起来都很好。但事后查看数据库确认所有查询在错误语句之后都失败。
$execute($ddl_full);
$execute($insert);
$execute($drop);
$execute($ddl_partial);
$execute($insert);
我正在迭代所有返回的行集,while ($statement->nextRowset())
如本答案所示,但它只打印了 8 次:
array(4) { [0] => string(5) "00000" [1] => int(0) [2] => string(24) " ((null)[0] at (null):0)" [3] => string(0) "" }
这加起来:
- 1 - 第一滴
- 1 - 完整的 ddl
- 3 - 第一次插入
- 1 - 秒下降
- 1 - 部分 ddl
- 1 - 插入的第一条语句(第二条是错误的,所以第三条永远不会执行)
为什么我没有从错误的声明中收到错误消息?
<?php
$hostname = 'microsoftsql.example.com';
$database = 'mydb';
$username = 'user';
$password = 'P@55w0rd';
// https://www.microsoft.com/en-us/download/details.aspx?id=50419
$driver = 'ODBC Driver 13 for SQL Server';
$pdo = new PDO("odbc:Driver=$driver;
Server=$hostname;
Database=$database",
$username,
$password
);
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$drop = "DROP TABLE testerino;";
$ddl_full = "
CREATE TABLE testerino (
value VARCHAR(10),
other VARCHAR(10)
);
";
$ddl_partial = "
CREATE TABLE testerino (
value VARCHAR(10)
);
";
$insert = "
INSERT INTO testerino (value)
VALUES ('first');
INSERT INTO testerino (value, other)
VALUES ('second', 'another');
INSERT INTO testerino (value)
VALUES ('third');
";
$execute = function (String $sql) use ($pdo) {
$pdo->beginTransaction();
try {
$statement = $pdo->prepare($sql);
$statement->execute();
do {
/* https://bugs.php.net/bug.php?id=61613 */
var_dump($statement->errorInfo());
} while ($statement->nextRowset());
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
throw $e;
} finally {
$statement->closeCursor();
}
};
$execute($drop); // not needed first time
$execute($ddl_full);
$execute($insert);
$execute($drop);
$execute($ddl_partial);
$execute($insert);
这对我来说是个大问题,因为从不抛出异常,所以事务不会回滚,我最终只插入了 1/3 记录。我需要它是全部或全部。
我正在运行带有 PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS ) 的 Ubuntu Linux 16.04.1,使用Microsoft® ODBC连接到 Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64)适用于 SQL Server® 的驱动程序 13(预览版)