SQLiteでは、AUTOINCREMENT
列は、テーブルに挿入される行ごとに自動的にインクリメントされる値を使用する列です。
AUTOINCREMENT
を作成する方法はいくつかあります。 列:
- 列を
INTEGER PRIMARY KEY
として定義すると、暗黙的に作成できます。 。 -
AUTOINCREMENT
を使用して明示的に作成できます キーワード。この方法の欠点の1つは、余分なCPU、メモリ、ディスクスペース、およびディスクI/Oオーバーヘッドを使用することです。
どちらの方法でも、NULL
で新しい行が挿入されるたびに、列は増分値を使用します。 その列に。
ただし、各方法の動作には微妙な違いがあります。
AUTOINCREMENTキーワードなし
列をINTEGER PRIMARY KEY
として宣言する場合 、自動的にインクリメントします。したがって、実際にAUTOINCREMENT
を使用する必要はありません。 キーワードを使用して、各行に自動的に増分する値を使用する列を作成します。
これを行うと、NULL
値は現在のROWID
に変換されます 。つまり、NULL
を挿入すると その列に、現在のROWID
に変換されます 。
実際には、その動作方法は、列がROWID
のエイリアスになることです。 。 ROWID
にアクセスできます 4つの名前のいずれかを使用した値。列名、ROWID
、_ROWID_
、またはOID
。
AUTOINCREMENT
を省略することの利点の1つ キーワードは、CPU、メモリ、ディスクスペース、およびディスクI/Oのオーバーヘッドを削減することです。
ただし、重要な欠点は、すべての行が昇順でインクリメントされることを保証できないことです。これは、AUTOINCREMENT
を省略した場合の自動インクリメントの仕組みによるものです。 キーワードとそのキーワードの使用。
AUTOINCREMENT
を省略した場合 キーワード、1回ROWID
が可能な最大の整数(9223372036854775807)に等しい場合、SQLiteは未使用の正のROWID
を見つけようとします。 ランダムに。
ただし、最大のROWID
を使用しない限り 値であり、最大のROWID
を持つテーブルのエントリを削除することはありません 、このメソッドは単調に増加する一意のROWID
を生成します s。
AUTOINCREMENTキーワードを使用
自動インクリメント列を明示的に作成することもできます。これを行うには、AUTOINCREMENT
を使用します キーワード。
この方法を使用する場合、自動インクリメント値を決定するためにわずかに異なるアルゴリズムが使用されます。
AUTOINCREMENT
を使用する場合 キーワード、ROWID
新しい行に選択されるのは、最大のROWID
より少なくとも1つ大きいです これまで 同じテーブルに存在する前。
つまり、以前に削除したROWID
に戻って再利用することはありません。 値。かつては可能な限り最大のROWID
が挿入されている場合、新しい挿入は許可されません。新しい行を挿入しようとすると、SQLITE_FULL
で失敗します。 エラー。
したがって、このメソッドを使用すると、ROWID
が保証されます。 sは単調に増加しています。つまり、ROWID
を持つためにこのメソッドに依存することができます s昇順。
ただし、これは値が常に1ずつ増加するという意味ではありません。それは、それらが決して減少しないことを意味します。
例
これは、自動インクリメント列を暗黙的に定義することと明示的に定義することの違いを示す例です。
CREATE TABLE Cats(
CatId INTEGER PRIMARY KEY,
CatName
);
CREATE TABLE Dogs(
DogId INTEGER PRIMARY KEY AUTOINCREMENT,
DogName
);
INSERT INTO Cats VALUES
( NULL, 'Brush' ),
( NULL, 'Scarcat' ),
( NULL, 'Flutter' );
INSERT INTO Dogs VALUES
( NULL, 'Yelp' ),
( NULL, 'Woofer' ),
( NULL, 'Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
初期結果:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
次に、各テーブルの最後の行を削除し、行を再度挿入して、結果を選択します。
DELETE FROM Cats WHERE CatId = 3;
DELETE FROM Dogs WHERE DogId = 3;
INSERT INTO Cats VALUES ( NULL, 'New Flutter' );
INSERT INTO Dogs VALUES ( NULL, 'New Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
結果:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
要約すると、猫 テーブルはなしで作成されました AUTOINCREMENT
キーワード、および犬 テーブルはで作成されました AUTOINCREMENT
キーワード。
猫から最後の行を削除した後 テーブル、次のINSERT
操作の結果、同じROWID
その行に再利用されています。
ただし、犬 テーブルが違いました。 AUTOINCREMENT
で作成されました キーワードであるため、以前の値を再利用することはできません。単に次の値にインクリメントし、番号付けにギャップを残します。
最大ROWID
前の例をさらに一歩進めて、最大のROWID
を明示的に使用することにより、新しい行を挿入できます。 可能です。
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
結果:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK、両方のテーブルが最大のROWID
として可能な最大の整数を使用します 値。
(自動インクリメント列の値を明示的に指定せずに)各テーブルに新しい行を挿入しようとするとどうなるか見てみましょう。
猫に挿入します テーブル:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
結果:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
つまり、猫 テーブルは成功しました。ただし、新しい自動インクリメント値が以前の値よりも低いことに注意してください(他のオプションはありません)。
行が挿入/更新された日付/時刻を記録する他の列がないと、 Magnusと誤って想定する可能性があります。 スクラッチの後に挿入されました 。
それでは、犬に新しい行を挿入してみましょう。 テーブル:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
結果:
Error: database or disk is full
したがって、猫とは異なる結果が得られます テーブル。
可能な限り最大のROWID
が原因で、このエラーが発生しました はすでにテーブルで使用されており、このテーブルはAUTOINCREMENT
で作成されているためです。 キーワード、それは戻って未使用のROWID
を検索しません 値。
SELECT * FROM Dogs;
結果:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
さらに、 Maximus を削除しても、このエラーが引き続き発生します テーブルから(つまり、ROWID
が最大の犬 値)。
試してみましょう:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
結果:
Error: database or disk is full
そのため、エラーが発生するだけでなく、 Maximusも削除しました :
SELECT * FROM Dogs;
結果:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
ROWID
を変更しても、これが発生することに注意してください。 値を低い値に。すでに9223372036854775807のROWIDを使用しているという事実は、AUTOINCREMENT
を意味します。 自動的にインクリメントしなくなります。
これは、AUTOINCREMENT
が原因です 同じテーブルにこれまで存在した値よりも少なくとも1つ高い値のみを使用します 。
今後、この列に値を挿入し続ける場合は、値を明示的に挿入する必要があります。これは、テーブルに9223372036854775807行がまだないことを前提としています。
マキシマスを再挿入しましょう ROWID
を低くします もう一度やり直してください:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
結果:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
それでは、リック可能を挿入してみましょう。 もう一度、AUTOINCREMENT
を使用します :
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
結果:
Error: database or disk is full
したがって、最大のROWID
を含む行を削除しましたが 9223372036854775807の値、それはまだ 列を自動インクリメントできなくなります。
これはまさにそれが設計された方法です。最大のROWID
以前はこのテーブルに含まれていたため、AUTOINCREMENT
そのテーブルで自動的に再びインクリメントすることはありません。
そのテーブルに新しい行を追加する唯一の方法は、ROWID
を手動で挿入することです。 値。
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
結果:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable