3

複数のクエリを実行するときに PDO に例外をスローさせるにはどうすればよいですか?

エラーのあるSQLを単独で実行すると:

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

次に、予想されるエラーが発生します。

PHP 致命的なエラー: Uncaught PDOException: SQLSTATE[42S22]: 列が見つかりません: 207 [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]列名 'other' が無効です。(/build/php7.0-41GaEn/php7.0-7.0.8/ext/pdo_odbc/odbc_stmt.c:260 の SQLExecute[207])

ただし、最初に適切な 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 - 2 回目のドロップ
  • 1 - 部分 ddl
  • 1 - 挿入からの最初のステートメント (2 番目のステートメントはエラーであるため、3 番目のステートメントは実行されません)

不適切なステートメントからエラー メッセージが表示されないのはなぜですか?

<?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 のレコードしか挿入されないからです。私はそれがすべてか無かである必要があります。

Microsoft® ODBCを使用して Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64) に接続する PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS ) で Ubuntu Linux 16.04.1 を実行しています。 SQL Server® 用ドライバー 13 (プレビュー)

4

0 に答える 0