1. ホーム
  2. データベース
  3. エスキューエルライト

SQLite3の自己追加型主キーに関連する知識のまとめ

2022-01-10 06:30:27

I. SQLiteはテーブルをクリアし、セルフインクリメントのカラムをゼロにします。

標準SQLでは、テーブルの内容をすべて消去するためにTRUNCATE TABLE文があります。
しかし、SQLiteはこのステートメントをサポートしていません。SQLite では DELETE FROM TableName を直接使用すればいいのです。
ほとんどのDBMSでは、TRUNCATEはテーブル全体にアクセスする必要がなく、データへの変更を記録する必要もないため、DELETEを使用することはTRUNCATEを使用することよりも高速ではありません。

SQLiteはTRUNCATEをサポートしていませんが、DELETEを最適化しています。
通常、テーブルを空にするときには、セルフインクリメントのカラムもゼロにする必要があります。SQLite でセルフインクリメントカラムを定義する方法は、以下の通りです。

コピーコード コードは以下の通りです。
CREATE TABLE TableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar, type Integer );

sqlite_sequenceという名前のテーブルは、SQLiteデータベースが自己インクリメントの列を含む場合、自動的に作成されます。
nameはセルフインクリメントのカラムがあるテーブルを記録し、seqは現在のシーケンス番号(次のレコードの番号は現在のシーケンス番号に1を足したもの)を記録します。
自己インクリメントの列をゼロにしたい場合、sqlite_sequenceテーブルを修正することでそうすることができます。

コピーコード コードは以下の通りです。
UPDATE sqlite_sequence SET seq = 0 WHERE name='TableName';

また、レコードを直接削除することも可能です。      

コピーコード コードは以下の通りです。
DELETE FROM sqlite_sequence WHERE name='TableName';

テーブルの自己インクリメントの列を全てゼロにするには、単にsqlite_sequenceテーブルを以下のように空にしてください。
コピーコード コードは以下の通りです。
DELETE FROM sqlite_sequence;

次に、SqliteにおけるINTEGER PRIMARY KEY AUTOINCREMENTとrowidの使用についてです。

sqliteでテーブルを設計しているとき、私の設計の各テーブルは主キーとして独自の形のid値を持っているという疑問が浮かびました。
/{br 実は、このようなid値を指定する代わりに、sqliteは内部的に各テーブルにrowidを追加し、それを暗黙のフィールドとして使用することができるのです。

内部のrowidを各テーブルのidの主キーにすればいいんじゃない?
自己増殖するフィールドを主キーとして使用する場合、メンテナンス性や大規模な分散型アプリケーションにおける主キーの競合の解決など、多くの問題があります。
一部の大規模な分散アプリケーションでは、主キーは通常guidであり、主キーの競合を効果的に回避し、主キーの維持作業を軽減することができます。
もちろん、中小規模のアプリケーションでは、自己増殖型フィールドがもう少し有益で、シンプルで、高速です。

Sqlite では、自己増殖型フィールドは INTEGER PRIMARY KEY AUTOINCREMENT として定義されます。
であれば、新しいデータを挿入するときに、このフィールドの値をNULLと指定するだけで、エンジンによって自動的に値が設定されます。
もちろん、NULLでない数値を設定して自分でこの値を指定することもできますが、その場合は自分でコンフリクトを起こさないように注意する必要があります。

新しいrowidの値は、最大数より前のランダムな未使用の値になります。つまり、rowidの値は、rowidが最大値に達するまで、厳密に単調に増加します。
INTEGER PRIMARY KEY AUTOINCREMENT 自己成長するフィールドのアルゴリズムは、rowidとは少し異なります。
まず、最大値に達した後、rowid は新しい値として削除されたフィールドに対応する rowid を探しますが、自己増殖型フィールドは SQLITE_FULL エラーをスローします。
次に、自己増殖型フィールドが新しい値を追加する場合、新しい値として一度も使用されていない行IDを探しますが、rowidは既存の最大行ID + 1を探します。

特に、id値に依存し、rowidではなくself-growingフィールドとの併用にしか適さない一部のメタレコードでは、アプリケーションへの影響はこちらの方が大きくなる可能性があります。
例えば、メタレコードのテーブルを設計してみよう。

コピーコード コードは以下の通りです。
Create table meta_struct(id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar, type Integer);

次に、他のテーブルの構造を記述するためのレベル1テーブルを定義する。
コピーコード コードは以下の通りです。
Create table meta_table(tableid INTEGER, table_field integer)

最後に、この主テーブルを元に、実際に使用する副テーブルを生成することができます。
この方法では、互換性のために、meta_structのidは一意でなければならず、フィールドが削除された場合、このフィールドのid値を再利用することはできず、さもなければデータベースマージ時に
プライマリテーブルとセカンダリテーブルが混同されます。そのため、meta_structテーブルの主キーは、rowidではなく、自己増殖型フィールドのみを使用することができます。

第三に、自己増殖型フィールドでは、エンジンが自動的に sqlite_sequence テーブルを生成して、各テーブルの自己増殖型フィールドの使用最大値を記録し、ユーザが
で、Update、Delete、Insertの操作が可能ですが、これを使うのはお勧めしません、エンジンを混乱させることになります。rowid を使用すると、ユーザが rowid の値を保持できるような内部テーブルも持つことになりますが、その値は見ることができません。