変数のいくつかの組み合わせが挿入されないようにする制約のあるテーブルがありますが、トランザクション内から不適切な値で挿入を実行すると、挿入は失敗しますが (当然のことですが)、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
)