0

変数のいくつかの組み合わせが挿入されないようにする制約のあるテーブルがありますが、トランザクション内から不適切な値で挿入を実行すると、挿入は失敗しますが (当然のことですが)、PDOException発生しません。実際、トランザクションは正常にコミットされたかのように動作しますが、次の select は値が挿入されていないことを示しています (レコードについては、同じ関数を使用して値の正しい組み合わせが挿入されています)。何がうまくいかないのですか?

以下は問題のある機能です。db_SqlSrv::pdo()の新しいインスタンスを作成して返しますPDO。私は sqlsrv ドライバーを使用しています。

/**
 * Inserts number of rules into <code>menu_availability</code> table.
 * The expected format for rules is:
 * <code>[{ menu_id: int,
 *          start: timestring,
 *          end: timestring,
 *          weekly: 0..6,
 *          once: datestring }, ...]</code>
 */
public static function addRules() {
    $rules = web_Util::getRequestParam('rules', 'json');
    if ($rules !== null) {
        $pdo = db_SqlSrv::pdo();
        try {
            $pdo->beginTransaction();
            foreach ($rules as $rule) {
                $statement = $pdo->prepare(
                    "insert into menu_availability
                     (menu_id, daily_serving_start, daily_serving_end,
                     weekly_service_off, one_time_service_off)
                     values (?, ?, ?, ?, ?)");
                $statement->bindParam(1, $rule->menu_id, PDO::PARAM_INT);
                if ($rule->start) {
                    $statement->bindParam(2, $rule->start, PDO::PARAM_STR);
                    $statement->bindParam(3, $rule->end, PDO::PARAM_STR);
                } else {
                      // This feels kind of stupid...
                    $rule->start = null;
                    $rule->end = null;
                    $statement->bindParam(2, $rule->start, PDO::PARAM_NULL);
                    $statement->bindParam(3, $rule->end, PDO::PARAM_NULL);
                }
                $statement->bindParam(4, $rule->weekly, PDO::PARAM_INT);
                $statement->bindParam(5, $rule->once, PDO::PARAM_STR);
                $statement->execute();
            }
            $pdo->commit();
        } catch (PDOException $e) {
            $pdo->rollBack();
            throw $e;
        }
    }
    return true;
}

テーブルの定義方法は次のとおりです。

if not exists (select * from sysobjects where name = 'menu_availability' and xtype = 'U')
create table menu_availability
   (menu_id int not null,
    daily_serving_start time(0) null,
    daily_serving_end time(0) null,
    weekly_service_off tinyint null,
    one_time_service_off date null,
    sn as case
       when ((daily_serving_start is null
              and daily_serving_end is null)
             and ((weekly_service_off is not null and one_time_service_off is null)
                  or (one_time_service_off is not null and weekly_service_off is null)))
            or
            ((daily_serving_start is not null
              and daily_serving_end is not null)
             and (one_time_service_off is null
                  or weekly_service_off is null))
             then cast(1 as bit)
        end persisted not null,
    constraint ch_valid_week_day
    check ((weekly_service_off is null)
        or (weekly_service_off <= 6 and weekly_service_off >= 0)));

制約制限をトリガーするデータの例:

{"menu_id":"18283","start":"","end":"","weekly":3,"once":"16-01-1901"}

weekly( と の両方を指定するのは違法ですonce)

4

1 に答える 1

0

PDO では、エラーが発生したときに例外をスローするよう明示的に指示する必要があります。デフォルトでは、エラーをトリガーせず、例外をスローしません。 と を使用して手動でエラーをチェックすることを期待していPDO::errorCode()ます。PDO::errorInfo()PDOStatement

呼び出すPDO::setAttribute()ことで、この動作を変更できます。通常、PDO 接続をセットアップするたびにこれを行います。

$db = new PDO($myDSN);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

これを行うと、PDO はエラーが発生するたびに例外をスローします。

接続はコンストラクターで行われ、これを処理する唯一の方法は例外であるため、この設定に関係なく、接続エラーは常に例外をスローすることにも注意してください。インスタンス化されています。これは、一般的にコンストラクターにビジネス ロジックを含めるべきではない理由の 1 つであり、そのような状況では柔軟性が大幅に低下します。

于 2013-03-07T23:34:12.413 に答える