![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0t_6Tm_FDozWOvjrJUjvi8GAXJI9BmjsywEfIHB19fzT-SCh79JKaEpULUwDB9YEb4x3tjs04NmY5Bi8CM8AKKUVV_iTP2DTyiaYKIae9K4fP2HOWpnCF6C9uJPHodHwL_dINlqJNb28Ajv3naGbn1cP5iyIVumY-Ncp0lR1C8bc5m856uLJEfZHP/s1600/sqlite.png)
最近仕事でSQLiteを使っているので、その時の備忘録です。
SQLでinsertしたデータを取得する時に、該当になるnameやカラムデータを指定して取得してもいいですが、それらがユニークでなければならないので、やはり登録後にid(unique)を取得したいです。
そのため、rowidという登録順に採番されるカラムデータとは別のIDを使って、最新データを取得するのが推奨されています。
last_insert_rowid()またはmax()で最新登録レコードのデータ取得ができる
Testテーブル
今回の検証用に新規にテーブルを作成します。
# sqlデータベースにアクセス(ファイルが無くてもアクセスできます)
$ sqlite3 test.sql
# テーブルを作成
sqlite > CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);
# 登録されたテーブルの確認
sqlite > SELECT * FROM sqlite_master WHERE type="table";
table|test|test|2|CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT)
# テストデータの登録
sqlite > INSERT INTO test (name) VALUES ("aaa");
sqlite > INSERT INTO test (name) VALUES ("bbb");
sqlite > INSERT INTO test (name) VALUES ("ccc");
# 登録されたデータ一覧の確認
sqlite > SELECT * FROM test
1|aaa
2|bbb
3|ccc
last_insert_rowid()
sqlite >SELECT * FROM test WHERE rowid=last_insert_rowid();
3|ccc
max()
sqlite >SELECT max(rowid),* FROM test;
3|3|ccc
rowidが取得出来ない確認ポイント
上記のようにコマンドで打ち込んでいると、どれも問題なく結果が出ると思いますが、phpなどでsqliteを使う時に、last_insert_rowid()を使って正常に登録したデータが取得できないケースがありました。
phpでのsqlite登録データの取得方法サンプルを見て、理解してください。
ダメパターン
<?php
add();
$data = inserted_data();
print_r($data);
function add(){
$sqlite = new \SQLite3('test.sql');
$res = $sqlite->exec('INSERT INTO test (name) VALUES ("ddd")');
$sqlite->close();
}
function inserted_data(){
$datas = [];
$sqlite = new \SQLite3('test.sql');
$res = $sqlite->query('SELECT * FROM test WHERE rowid=last_insert_rowid()');
while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
array_push($datas , $row);
}
$sqlite->close();
return $datas;
}
データは登録出来ていましたが、結果は取得できていません。
成功パターン
<?php
$data = add();
print_r($data);
function add(){
$datas = [];
$sqlite = new \SQLite3('test.sql');
$sqlite->exec('INSERT INTO test (name) VALUES ("ddd:'.date('YmdHis').'")');
$res = $sqlite->query('SELECT * FROM test WHERE rowid=last_insert_rowid()');
while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
array_push($datas , $row);
}
$sqlite->close();
return $datas;
}
これで正常に登録データを取得することが出来るようになりました。
SQLite3で作成したインスタンスをclose()する前じゃないと、last_insert_rowid()が取得できないようでした。
あとがき
関数を個別に分けてmax()を使ってデータを取得すればいいかと思いがちですが、
insertが頻繁に行われるシステムの場合に、複数人が同時アクセスをして、データを同時にinsertした場合、自分が登録したデータではない、最新データが返ってしまう可能性があります。
いわゆる
排他処理をするために、last_insert_rowid()を使ったほうが問題が起きにくくなるという事が理解できました。
そもそも、sqlのinsertで、rowidを返してくれる仕様にしてくれればいいのに、なんともめんどくさい限りです。