SQLiteは、AUTOINCREMENTの情報を sqlite_sequence というテーブルで管理してるみたいです。これの挙動を調べてみました。
基本
まず、PKが連番のテーブルを適当に作ります。
この時、まだデータベース内に sqlite_sequence テーブルが存在しなければ作成されます。
sqlite_master を覗いて定義を見てみると、sqlite_sequence テーブルは name と seq という名前のカラムを持ってることが分かります。
次に、先程作成したテーブル (PKが連番) にレコードを追加します。
すると sqlite_sequence に、テーブル名と連番を記録するレコードが追加されました。
ここでは my_table に1を振った状態になっています。sqlite_sequence の seq は、最後にレコードを追加した時に振られた連番です。
以後はレコードを追加すると、この数字が増えていきます。
テーブルを DROP
すると、sqlite_sequence の当該テーブルのレコードも消えます。これで sqlite_sequence がカラになった場合は、sqlite_sequence ごと消えるみたいです。
sqlite_sequence を消すと
意地悪してみます。sqlite_sequence を勝手に DELETE
してしまいました。(DROP
はエラーになるのでできません。)
この状態でさらに my_table にレコードを追加してみます。
すると、自動的に sqlite_sequence が復活しました。値は3です。
復活するときの値は、レコード追加前に my_table に存在した連番の最大値から決定されるみたいです。ここまでの結果に続けて、以下の操作を行うと確認できます。
my_table にかつて存在したはずの4番が居ないので、復活時にもう一度4番が回ってきました。
sqlite_sequence を巻き戻すと
もっと意地悪してみます。今度は sqlite_sequence を勝手に UPDATE
して、過去の番号に戻してしまいます。
sqlite_sequence の seq が、実際に存在しているレコードより巻き戻った状態になりました。このまま4番目のレコードを追加してみます。
追加されたレコードに振られた連番は4でした。ということは、レコード追加時に連番が重複した場合も、テーブルに現存する連番の最大値で自動的に調整されるようです。上述した sqlite_sequence のレコードを消した場合のパターンと同じですね。
sqlite_sequence を進めると
逆のパターンもやっておきます。sqlite_sequence を勝手に UPDATE
して、もっと先の番号に進めてしまいます。
sqlite_sequence の seq が、実際に存在しているレコードより先に進んだ状態になりました。このまま2番目のレコードを追加します。
追加されたレコードに振られた連番は10でした。先に進める分には、変更した結果がそのまま反映されます。
というか普通に使ってても、物理削除したレコードの連番を勝手に詰められたら困るから、これは当然でしたね。