4

さて、私はこれに困惑しています。PDO 経由で行を削除できないように見えるデータベースにテーブルがあります (数週間前からこの動作に気付きましたが、それ以前は完全に機能していました)。

私のPHPコードはこれです:

    // Echo's have been added for testing.
    try{
            $dbh = new PDO($hostname, $username, $password);

            $sql="delete from sources where workFlowID=".$ID.";";
            $numRows=$dbh->exec($sql);
            echo "There were $numRows deleted with: $sql <br><br>";

            $sql="delete from workflow where id=".$ID." limit 1;";
            // I have only put the 'or die' section in this today to try to see where
            // it was having problems. It carries through happily as the output 
            // below shows.
            $numRows=$dbh->exec($sql) or die(print_r($dbh->errorInfo(), true));
            // This is the problem delete...
            echo "There were $numRows deleted with: $sql <br><br>";

            $dbh=null;

    }
    catch(PDOException $e){
            echo 'Error : '.$e->getMessage();
            exit();
    }

次の出力で:

    There were 1 deleted with: delete from sources where workflowid=1;

    There were 1 deleted with: delete from workflow where id=1 limit 1;

しかし、データベースを見ると、自分のレコードがまだworkflowテーブルにあることがわかります。

データ型を確認し、再確認しました。ID と workflowID はどちらも int です。それらには、数行離れた同じ変数が提供されています。

パーミッションの問題かもしれないと思ったので、次のようにまとめました。

    mysql> grant all privileges on storeProcess.* to 'myusername'@'localhost' with
     grant option;
    Query OK, 0 rows affected (0.19 sec)

次に、タイミング/過負荷/誰が何を知っているかなどの奇妙なタイミングかもしれないと考えたので、ワークフロー テーブルにトリガーを作成して、アプリケーションの作業を実行し、他のテーブルをクリーンアップしました。次に、PHP コードを次のように変更しました。

    // Echo's have been added for testing.
    try{
            $dbh = new PDO($hostname, $username, $password);

            $sql="delete from workflow where id=".$ID." limit 1;";
            $numRows=$dbh->exec($sql) or die(print_r($dbh->errorInfo(), true));
            echo "There were $numRows deleted with: $sql <br><br>";

            $dbh=null;

    }
    catch(PDOException $e){
            echo 'Error : '.$e->getMessage();
            exit();
    }

出力は次のようになります。

    There were 1 deleted with: delete from workflow where id=1 limit 1;

しかし、繰り返しますが、記録はまだそこにあります。

    mysql> select count(*) from workflow where id=1;
    +----------+
    | count(*) |
    +----------+
    |        1 |
    +----------+
    1 row in set (0.00 sec)

もちろん、PDO が使用しているアカウントのユーザー名/パスワードを使用してログインしている場合、まったく同じコマンドを使用してコンソールからレコードを削除しても問題はありません (トリガーは正常に機能し、残りのテーブルからもデータを削除します)。

    mysql> delete from workflow where ID=1;
    Query OK, 1 row affected (0.00 sec)

    mysql> select count(*) from workflow where id=1;
    +----------+
    | count(*) |
    +----------+
    |        0 |
    +----------+
    1 row in set (0.00 sec)

それで、何がうまくいかないのですか?

これは私の仕事用デスクトップ (Win XP、大企業の標準タイプの SOE) で実行されています。

これらのクエリ中にトランザクションを使用していません。さらに、このアプリを使用しているユーザーはごくわずかで、CPU 使用率が高くなることはありません。

コードとスキーマを家に持ち帰り、Linux でテストし、戻ったら結果を投稿します。

更新: 自宅の Linux システムに移動しました。まったく変化なし。

編集:

これに提案されているように、コードを変更しました:

try{
    $dbh = new PDO($hostname, $username, $password);
    $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql="delete from sources where workflowid=".$ID.";";

    //echo $sql."<br><br>";

    $numRows=$dbh->exec($sql);
    echo "There were $numRows deleted with:<b> $sql </b><br><br>";

    $sql="delete from workflow where id=".$ID." limit 1;";
    $numRows=$dbh->exec($sql);
    echo "There were $numRows deleted with:<b> $sql </b><br><br>";

    $sql="delete from workflow where id=".$ID." limit 1;";
    $numRows=$dbh->exec($sql);
    echo "There were $numRows deleted with:<b> $sql </b><br><br>";

    $dbh=null;

}
catch(PDOException $e){
    echo 'Error : '.$e->getMessage();
    //exit();
}

次の出力で実行しました。

There were 601 deleted with: delete from sources where workflowid=77;

There were 1 deleted with: delete from workflow where id=77 limit 1;

There were 0 deleted with: delete from workflow where id=77 limit 1; 

行はまだ削除されていません:

mysql> select count(*) from workflow where id=77;
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)
4

1 に答える 1

3

このPDO::exec()関数は、影響を受ける行がない場合は 0 を含む、影響を受ける行の数を返します。

このような行は、boolean false として解釈されるwill を返すdie()ためです。exec0

$dblink->exec("UPDATE `sometable` SET `somecolumn`=0 WHERE `somecolumn`=0") or die("Never use die for error handling.");

PDO の最良のエラー処理方法は、PDO 例外を使用することです。次のように PDO 例外 (PDOException クラスの、ドキュメントを参照) を有効にします。

//enable Exception mode (uncaught exceptions work just like die() with the benefit of giving you details in logs of where execution was stopped and for what reason)
$pdoDBHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

例外モードを削除or die()して有効にします。exit();これで「奇妙な」問題が解決するに違いありません。また、手続き型コードを使用した場合でも、PHP で例外をスローする方法を見てください (die()およびexit().

BTWexitは と同じようdieに実行を停止しますが、オペレーティング システムに成功/エラー コードを返すため、CLI モードで便利です。これは実際にはエラー処理を目的としたものではありません。

于 2012-08-03T07:10:45.557 に答える