ZawaWorks’s diary

プログラミング技術メモ

SQLite:上から何番目の行を削除したい

はじめに

最近、大学でSQLiteを習ったのですが、データベースを作成中「上から〇番目のものを消したいな」と思ったのですが、それが上手くいかなかったのでいろいろと調べてみました。

使うテーブル

テーブル名:user

id name
2 tanaka
5 kato
7 maeda

LIMITとOFFSET

SELECT文ではLIMITとOFFSETという変数を指定するだけで、上から何番目の行を指定することができます。

LIMIT

limitというのは抜き出した行(またはパラメータ)の数を制限する命令です。 たとえば

SELECT * FROM user LIMIT 2;

としたときの結果は以下の表になります。

id name
2 tanaka
5 kato

OFFSET

OFFSETというのは行を取得するときの開始位置を決める命令です。 LIMITを使用しているときのみ使用可能です。

たとえば

SELECT * FROM user OFFSET 1;

と書くとエラーを吐きます。

実際に使用するときは

SELECT * FROM user LIMIT 2 OFFSET 1;

と書きます。その結果は以下の表になります。

id name
5 kato
7 maeda

上からk番目を取得したいとき

以上のことを踏まえると上からk番目を取得する書き方は以下のようになります。

SELECT * FROM user LIMIT 1 OFFSET k-1;

上からk番目を削除したい

これをDELETE文でもできないかと思い以下のようなコマンドを書きました。

DELETE FROM user LIMIT 1 OFFSET k-1;

しかし、このコードはエラーを吐いてしまいました……。 どうしてかと思い調べてみるとこんな図がありました。

f:id:ZawaWorks:20171207233626p:plain

SQLite Syntax: delete-stmt-limitedより引用

つまりはDELETE文ではLIMITOFFSETも使えないらしいです。

SELECT文と組み合わせる

じゃあ、上からk番目を消すことができないのかというと別にそういうわけではなく、SELECT文と組み合わせると可能になるようです。

delete from user where id = (select id from user limit 1 offset k-1);

(select id from user limit 1 offset k-1)は上からk番目の行のidを取得しています。そのidと同じ行を削除すれば結果的に上からk番目の行を削除できるというわけです。

おわりに

今回はDELETE文でスマートに上からk番目を削除したかったのですが、どうやら仕組み的に間接的な方法しかないことが分かりました。 ただ正直、遠回りな分コマンドが長くなってしまうのはあまり好きではないですね……。

参考資料

SQLite Query Language: DELETE