PDO does not throw exception with multiple queries

只谈情不闲聊 提交于 2019-11-28 05:29:16

问题


How can I get PDO to throw an exception when executing multiple queries?

If I run the erroneous sql by itself:

$execute($ddl_partial);
$execute($insert);

Then I get the expected error:

PHP Fatal error: Uncaught PDOException: SQLSTATE[42S22]: Column not found: 207 [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Invalid column name 'other'. (SQLExecute[207] at /build/php7.0-41GaEn/php7.0-7.0.8/ext/pdo_odbc/odbc_stmt.c:260)

However, if I run some good SQL first and follow it up with the bad, then it just swallows the error and all appears fine. But looking at the database afterwards confirms all queries fail after the bad statement.

$execute($ddl_full);
$execute($insert);

$execute($drop);
$execute($ddl_partial);
$execute($insert);

I'm iterating over all the returned rowsets with while ($statement->nextRowset()) as is demonstrated in this answer, but it only prints this exactly 8 times:

array(4) {
  [0] =>
  string(5) "00000"
  [1] =>
  int(0)
  [2] =>
  string(24) " ((null)[0] at (null):0)"
  [3] =>
  string(0) ""
}

which adds up:

  • 1 - first drop
  • 1 - full ddl
  • 3 - first inserts
  • 1 - second drop
  • 1 - partial ddl
  • 1 - first statement from insert (second one is erroneous, so third never executes)

Why am I not getting the error message from the bad statement?

<?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);

This is a big problem for me because an exception is never thrown, so the transaction doesn't roll back and I end up with only 1/3 records inserted. I need it to be all or nothing.

I'm running Ubuntu Linux 16.04.1 with PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS ) connecting to Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64) using the Microsoft® ODBC Driver 13 (Preview) for SQL Server®

来源:https://stackoverflow.com/questions/40116280/pdo-does-not-throw-exception-with-multiple-queries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!