【プログラミング】SQLite3:データの最後の行を取得(last_insert_rowid()ではなくmax())

  • URLをコピーしました!
目次

SQLite3

前回、データフレームから特定の行を抽出し、新しいデータフレームに高速に移す方法を紹介しました。

今回は自分がプログラミングしていてハマった部分の解説をしたいと思います。

ハマったのはSQLite3でデータベースの最後の行を取得することです。

例えばこんな感じでデータベースを作成したとします。

(今回は便宜上PythonからSQLite3を使いますが、SQLite3のコマンドだけ注目してください)

import sqlite3

dbname = 'test9-1.db'
with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    cur.execute("CREATE TABLE table1(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
    cur.execute("INSERT INTO table1(id, name, age) values(1, 'Sato', 10)")
    cur.execute("INSERT INTO table1(id, name, age) values(2, 'Suzuki', 15)")
    cur.execute("INSERT INTO table1(id, name, age) values(3, 'Takahashi', 20)")

表示してみるとこんな感じです。

with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    data = cur.execute("SELECT * FROM table1").fetchall()
    print(data)

実行結果
[(1, 'Sato', 10), (2, 'Suzuki', 15), (3, 'Takahashi', 20)]

今回はこの最後の「(3, ‘Takahashi’, 20)」を取得したい、もしくはさらにデータが追加されたらその時の最後のデータを取得したいというわけです。

それでは始めていきましょう。

last_insert_rowid()ではダメ?!

「SQLite3 最後の行」でググるとよく見るのが「last_insert_rowid()」というコマンド。

どうやらこれで最後の行のrowidを取得することができるので、WHEREでrowidをとして指定してやれば最後の行が取得できるらしい。

ということで先ほど作成したデータベースで試してみました。

with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    lastdata = cur.execute("SELECT * FROM table1 WHERE rowid = last_insert_rowid()").fetchall()
    print(lastdata)

実行結果
[]

取得できていません。

PythonからSQLite3を動かしているのが悪いのかと思い、ターミナルからSQLite3を動かして試してみてもダメ。

さて何が悪いのかと思い、とりあえずデータベースを作成した直後に「last_insert_rowid()」を試してみました。

import sqlite3

dbname = 'test9-2.db'
with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    cur.execute("CREATE TABLE table1(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
    cur.execute("INSERT INTO table1(id, name, age) values(1, 'Sato', 10)")
    cur.execute("INSERT INTO table1(id, name, age) values(2, 'Suzuki', 15)")
    cur.execute("INSERT INTO table1(id, name, age) values(3, 'Takahashi', 20)")
    lastdata = cur.execute("SELECT * FROM table1 WHERE rowid = last_insert_rowid()").fetchall()
    print(lastdata)

実行結果
[(3, 'Takahashi', 20)]

今度は取得できました。

なんだなんだできるじゃないか、データベースが悪かったのかと思い、再度別のセルで試してみました。

with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    lastdata = cur.execute("SELECT * FROM table1 WHERE rowid = last_insert_rowid()").fetchall()
    print(lastdata)

実行結果
[]

今度は取得できません。

ここまできてなんとなく分かってきました。

「last_insert_rowid()」は「SQLite3が”起動している間”での最後に挿入されたデータのrowid」を取得するコマンドのようです。

つまり一度SQLite3を閉じて、再度起動した場合は「last_insert_rowid()」でのrowidは取得できないということです。

もちろんSQLite3を常時開いておくなんてことはできないので、この方法では目的は達成できませんでした。

max()でrowidの最大値を取得

そこで代わりに用いたのが「max()」です。

これでrowidの最大値のデータだけを取得すれば、データの最後の行を取得できるというわけです。

ということで最初に作成したデータベース(test9-1.db)に対して試してみました。

import sqlite3

dbname = 'test9-1.db'
with sqlite3.connect(dbname) as conn:
    cur = conn.cursor()
    lastdata = cur.execute("SELECT max(rowid), * FROM table1").fetchall()
    print(lastdata)

実行結果
[(3, 3, 'Takahashi', 20)]

ちゃんと取得することができました。

ちなみにこの方法で取得すると、取得したデータの最初の値はrowidとなり、いつもより値が一つ多いので気をつけてください。

次回はTwitter API v2でいいねやリツイートの数などを取得してみます。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次