【PHP】SQLServerのトランザクションの確認、操作方法
【PHP】SQLServerのトランザクションの確認、操作方法
データベースを操作する際、実際のアプリでは必ずトランザクションの使用します。
SQLServerのトランザクションの操作方法を紹介します。
そもそもなぜトランザクションが必要なのか
トランザクションが必要なケースは、例えば、店舗1から店舗2にりんごを10個送ったとします。データベース上では店舗1から在庫を減らして店舗2の在庫を増やすという処理が必要ですが、店舗1のSQLだけ成功して店舗2のSQLが失敗した場合、在庫数がおかしくなります。
そこでトランザクションが必要となります。
トランザクションとは何か?については、【MySQL】トランザクションとACID特性を参考にしてみてください。
トランザクションの書き方
店舗1から店舗2にりんごを10個送ったとします。
その場合は、以下のように記述します。
try {
$user = 'hoge';
$pwd = 'hoge';
$host = 'localhost';
$dbName = 'hoge_db';
$dsn = "mysql:host={$host};port=8889;dbname={$dbName};";
$conn = new PDO($dsn, $user, $pwd);
// 連想配列のみ出力
$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// エラーを有効にする
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare()を使うための設定
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$product_id = 2;
$from_shop_id = 1;
$to_shop_id = 2;
$amount = 20;
// pst = prepared statement
$pst = $conn->prepare('
update txn_stocks
set amount = amount + :amount
where shop_id = :shop_id
and product_id = :product_id
');
// トランザクションを開始する
$conn->beginTransaction();
// 在庫を足す
$pst->execute([
':amount' => $amount,
':shop_id' => $to_shop_id,
':product_id' => $product_id
]);
// 在庫を減らす
$pst->execute([
':amount' => -1 * $amount,
':shop_id' => $from_shop_id,
':product_id' => $product_id
]);
// 成功したときにcommitでデータを反映
$conn->commit();
} catch (PDOException $e) {
echo 'エラーが発生しました。
';
echo $e->getMessage();
// コネクションが失敗したとき
$conn->rollBack();
}
トランザクションを開始するには、以下のように記述します。
// トランザクションを開始する
$conn->beginTransaction();
これ以降は同じセッションとして扱われます。
例外処理try-catchを記述して、
// 成功したときにcommitでデータを反映
$conn->commit();
上の記述で成功したときのデータをデータベースに反映されることができます。
在庫数などはunsignedなどマイナスにならないように通常は設定しているため、在庫数を減らしてマイナスになる値になるとエラーになります。
そのとき、catchブロックに処理が飛びます。
データベースに反映させたくないため、rollBack()で巻き戻します。