導入
データベース管理において、発行したSQLが「実際に何行に対して影響を与えたか」を確認することは、バッチ処理の整合性チェックや、誤操作の未然防止において非常に重要です。特にトランザクション内で複雑なUPDATEやDELETEを行う際、意図した行数が処理されたかをリアルタイムで検証できれば、予期せぬデータ欠損や更新漏れを早期に検知できます。今回は、SQLiteで手軽にこの検証を行える「changes関数」について解説します。
基礎知識
SQLiteには、データ操作の結果を追跡するための関数がいくつか用意されています。
changes関数は、直前に実行されたINSERT、UPDATE、DELETE文によって直接影響を受けた行数を返す関数です。
一方、total_changes関数は、現在のデータベース接続が開始されてから実行されたすべてのSQL文による影響行数の合計を返します。
今回紹介するchanges関数は、直前のステートメントの結果のみをピンポイントで確認したい場面に適しています。
実装/解決策
changes関数は引数を取らず、SELECT文と組み合わせて呼び出すだけで使用可能です。注意点として、直前のSQLがSELECT文などの参照系であった場合や、何も処理が行われなかった場合は「0」が返されます。また、トリガーによる影響行数はカウントに含まれない(あるいはトリガー自体の影響は考慮されないケースがある)ため、複雑なスキーマで運用している場合は注意が必要です。
サンプルプログラム
以下のコードは、テーブル作成からデータ操作、そしてchanges関数を用いた行数確認の一連の流れです。
— 1. テスト用テーブルの作成
create table staff(id integer primary key, name text, address text);
— 2. データの挿入
insert into staff(name, address) values(‘Yamada’, ‘Tokyo’);
insert into staff(name, address) values(‘Suzuki’, ‘Osaka’);
— 直近の挿入結果を確認(期待値: 1)
select changes() as affected_rows;
— 3. データの更新
— ‘Osaka’を小文字の’osaka’に統一する操作を想定
update staff set address = ‘osaka’ where address = ‘Osaka’;
— 更新行数を確認(期待値: 1)
select changes() as affected_rows;
— 4. データの削除
delete from staff where address = ‘Tokyo’;
— 削除行数を確認(期待値: 1)
select changes() as affected_rows;
— 5. 該当なしのケース
delete from staff where address = ‘Fukuoka’;
— 一致する行がない場合、changesは0を返す
select changes() as affected_rows;
応用・注意点
実務における注意点は以下の2点です。
1. トランザクションとの併用: トランザクション内で複数の更新を行う場合、必ず各文の直後にchanges関数を実行してください。間に別のSQLを挟むと、値が上書きされてしまいます。
2. トリガーの影響: トリガーが定義されているテーブルに対してSQLを実行した場合、changes関数が返す値は「トリガーによって処理された行数」を含まない場合があります。厳密な行数カウントが必要な業務ロジックでは、トリガーの挙動を事前に検証しておくことが推奨されます。
これらの関数を適切に活用することで、アプリケーション側のログ出力やエラーハンドリングがより堅牢なものになります。ぜひ開発中のデバッグやデータメンテナンスにお役立てください。

コメント