XACT ABORTを使って途中でエラーになったトランザクションをロールバックする
一つのsqlファイルの中に複数INSERT文を書きまとめて実行する時、途中で一意制約違反エラーになったらどうするか 初期状態
code:cmd.sql
SELECT name, address, tell FROM SAMPLE_TABLE;
table:result.csv
name address tell
Go Japan 070-7777-7777
INSERT
code:cmd.sql
BEGIN TRANSACTION;
INSERT INTO SAMPLE_TABLE VALUES('Go','Japan','090-9999-9999');
INSERT INTO SAMPLE_TABLE VALUES('Go','Japan','080-8888-8888');
INSERT INTO SAMPLE_TABLE VALUES('Go','Japan','070-7777-7777');--これが重複する
INSERT INTO SAMPLE_TABLE VALUES('Go','Japan','060-6666-6666');
COMMIT;
エラーになる直前まではINSERTされてしまう
実行失敗している時点で、だいたい焦っている
トランザクションが入れ子になっていたりすると
デメリットは?
調べた感じ、ロールバックできそうな方法は2つ
入れ子のBEGIN TRANSACTIONの中でROLLBACKすると全体がロールバックされる
BEGIN TRANSACTION transaction_nameでトランザクションに名前を割り当てたらできそう
使ってるツールによって挙動違うとかある?
今トランザクション中だよみたいな状態ってわかる?
BEGIN TRANSACTIONで1増える
COMMITで1減る
ROLLBACKで0に
複数データINSERTしている場合成功しているものは残ってしまう
戻せないの?
ROLLBACKすれば戻せる
トランザクションの状態は続いているから
@@TRANCOUNTでわかる
1個失敗したら全部ロールバックしてほしい…
オプションである
ONにすると@@OPTIONSに+16384
16384 XACT_ABORT Transact-SQL ステートメントで実行時エラーが発生した場合、トランザクションをロールバックします。
XACT_ABORT ONのデメリットがいまいちわからない
途中までの処理までロールバックしないようにということなんだろうけど…
複数のクエリをまとめて処理する時って、「辻褄があう一連の処理」になるように作る気がする
ユーザー情報テーブルをUPDATE、次に関連するテーブルをINSERT...みたいな
開発用のDBで動かして問題がなければ、それをまるっと本番用のDBで動かす
開発用DBと本番用DBでデータにちょっと差異があって本番でコケた!
事前に検証したはずなのに!(原因は色々)
もう一回やりなおしたい!
「とりあえず失敗したところまでは反映しておいたわ」で嬉しいパターンがあんまり思いつかない
めちゃくちゃ件数が多いからとにかく成功するまで突っ込みたいとか?
↓これだと(誤ってCOMMITしたら)テーブルの状態が変わってしまわない?
トランザクション開始しました
INSERT実行しました
99件目までは成功してるんで突っ込んでます
COMMIT or ROLLBACK待ち…