1. 導入
データベース開発において、「今まさにINSERTしたレコードの情報を、続けて処理したい」というケースは頻繁に発生します。例えば、親テーブルにデータを保存した後、そのIDを使って子テーブルに紐づくデータを登録するような場合です。SQLiteでは、last_insert_rowid()関数を使うことで、アプリケーション側で複雑なクエリを発行することなく、安全かつ簡潔に直近のIDを取得し、後続の処理に活かすことができます。
2. 基礎知識
SQLiteのテーブルには、明示的に指定しなくても内部的にROWIDと呼ばれる一意の64ビット整数値が各行に割り当てられています。特に、INTEGER PRIMARY KEYを指定した列は、このROWIDのエイリアス(別名)として機能します。last_insert_rowid()は、そのデータベース接続において、最後にINSERT文が実行されたテーブルのROWIDを返す組み込み関数です。この関数は、他のユーザーによる同時実行の影響を受けないため、マルチユーザー環境でも安全に使用できるのが大きなメリットです。
3. 実装/解決策
この関数を最も効果的に使う場面は、INSERT直後のSELECT文のWHERE句です。これにより、直前に挿入したデータを即座に特定して詳細情報を取得したり、その行に対してUPDATE処理を行ったりすることが可能になります。
4. サンプルプログラム
以下は、スタッフ管理テーブルに対して新規データを追加し、そのROWIDを利用して直後のレコードを抽出する一連の流れです。
— スタッフテーブルの作成
CREATE TABLE staff (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
— データの挿入
INSERT INTO staff (name) VALUES (‘Tanaka’);
— last_insert_rowid()を使用して、今挿入したばかりのレコードを取得する
— 複数のユーザーが同時に接続していても、自身のセッションの直近値のみを取得するため安全です
SELECT FROM staff WHERE rowid = last_insert_rowid();
— 応用:取得したROWIDを変数に保持して、別のテーブル(例:給与テーブル)への登録に利用する
— INSERT INTO salary (staff_id, amount) VALUES (last_insert_rowid(), 300000);
5. 応用・注意点
現場で運用する上で、以下の点には注意してください。
・セッションスコープの理解
last_insert_rowid()は「そのデータベース接続(コネクション)」単位で値を保持しています。他の接続がINSERTを行っても、自分の関数の結果には影響しません。逆に言えば、接続を閉じて再接続すると値はリセットされます。
・トリガーとの併用
もしテーブルにトリガーが設定されており、トリガー内で別のテーブルへのINSERTが行われた場合、last_insert_rowid()が返す値は「トリガーによって最後に挿入された行」になります。メインのテーブルのIDを取得したい場合は注意が必要です。
・トランザクションと併用する
一連の処理が整合性を保つよう、INSERTからROWIDの取得までの処理は必ず同一のトランザクション内で行うように設計してください。これにより、データ整合性が保証された堅牢なシステム構築が可能になります。

コメント