2009-06-13 57 views
11

私はSQLiteデータベースに関する純粋に学問的な質問があります。SQLite DBのアイデンティティ列の最大値

私は私のWinFormプロジェクトでデータベースを使用するSQLite.netを使用しています、と私は新しいテーブルを設定されたとして、私は、ID列の最大値を考えるになりました。

IDENTITY[ID]コラムに使用します。これは、SQLite.net DataType Mappingsによれば、DbType.Int64に相当します。私は通常、自分のID列をゼロ(テストレコードとしてその行を持つ)で開始し、データベースを自動インクリメントします。

最大値(Int64.MaxValue)が9,223,372,036,854,775,807あります。私の目的のために、私はその最大値に達するまで表面を傷つけることは決してありませんが、データベースではどうなりますか?これを読んでみると、ID列が一意でなければならないため、DB2は負の値(-9,223,372,036,854,775,807)に値を近づけてそこからインクリメントするように見えることがわかりました。

これはSQLiteやその他のデータベースエンジンではどうなりますか?

+0

SQLiteの公式ドキュメントはhttp://www.sqlite.org/autoinc.htmlでこれをカバーしています。 –

答えて

24

1秒あたり100万行が挿入されていると、ラップアラウンド・リスク・ポイントに達するには約292,471年かかり、データベースはそれに比べてごくわずかです時間(実際には、ホモサピエンス;-)しています。

+1

私はいつも問題のことに気をつけると、この種の正気チェックが好きです。しかし、私は通常それらを考えるべきではありません。 : -/ – tgray

+3

ほとんど「小さな部分」。ウィキペディアhttp://en.wikipedia.org/wiki/Homo_sapiensによると、ホモサピエンスはその時代の3分の2を占めています。 –

1

私は特定のDB2の実装ロジックに話すことはできませんが、あなたが記述「ラップアラウンド」動作がtwo's complementを経由して署名を実装番号の標準です。

実際に何が起こるかについては、データベースがどのようにそれを処理するかについて、大気中に完全に浮上しています。この問題は、エンジンが内部的に64ビット以上のデータ型を使用することは考えにくいため、実際にフィールドには大きすぎるIDを実際に作成する時点で発生します。その時点で誰もが推測している...エンジンを開発するために使用される内部言語が暴れる可能性があり、その数は黙って回り込み、主キーの違反を引き起こす可能性がある(IDが矛盾していると仮定すると)、世界はあなたのオーバーフローのために終了します。

しかし、実際には、アレックスは正しいです。理論的な制限は、ここに含まれる行の数(行ごとに1つのidと仮定し、どんな種類の詐欺師の身分証明書を挿入してもかまいません)では、基本的には状況を欺くものになります。私たちは、とにかくすべて死んだよでも膨大挿入率、それは:)問題ではありませんので、

7

IDENTITYは、実際のSQLiteで自動インクリメントに適切な方法ではありません。それはあなたがアプリケーション層でインクリメントを行う必要があります。 SQLiteシェルでは、次のように試してみてください:

create table bar (id IDENTITY, name VARCHAR); 
insert into bar (name) values ("John"); 
select * from bar; 

idは単にnullです。 SQLiteはIDENTITYに特別な意味を与えませんので、基本的には普通の(型なしの)列です。私はあなたが期待だと思うよう

create table baz (id INTEGER PRIMARY KEY, name VARCHAR); 
insert into baz (name) values ("John"); 
select * from baz; 

それは1になります:あなたがしなければ一方

、。

there is also INTEGER PRIMARY KEY AUTOINCREMENTいます。基本的な違いは、AUTOINCREMENTはキーが決して再使用されないことを保証することです。だから、もしあなたがジョンを取り除くと、1は決してIDとして再利用されません。いずれにしても、PRIMARY KEY(オプションのAUTOINCREMENTを使用)を使用してIDを使い果たした場合、SQLiteはSQLITE_FULLで失敗してしまいます。

IDENTITYを使用すると、のアプリケーションがDBが一杯になったときに正しくラップアラウンドする可能性があります(おそらく無関係)可能性があります。これは、SQLiteのIDENTITYカラムに任意の値(負のintを含む)を保持できるため、可能です。もう一度試してみてください:

insert into bar VALUES ("What the hell", "Bill"); 
insert into bar VALUES (-9, "Mary"); 

これらはどちらも完全に有効です。それらはbazにも有効です。 とbazを使用すると、idを手動で指定することを避けることができます。そうすれば、ID列には決して迷惑メールはありません。

+1

興味深い情報、私はそれを見なければならないでしょう。今、Visual Studio 2008データベースデザイナーでデータベースを作成します。常にループのために私をスローすることは、sqlite自体がtyplessなので、私は通常、データ型を調べるためにリンクしたページを使用し、最初の列をName:ID、Type:integer、nullを許可しない列を主キーに設定します。私は実際にはSQLiteシェルに慣れていません。しかし、情報をありがとう! –

3

http://www.sqlite.org/autoinc.htmlの文書では、ROWIDは、最大数に達した時点で、使用されていない値をランダム化によって見つけようとします。最大値がテーブルにあった後、それは、このテーブルに挿入するすべての試みにSQLITE_FULLで失敗するAUTOINCREMENTについて

テーブルは、以前は可能な限り最大のROWIDを持つ行を保持している場合、新しいINSERTは許可されず、新しい行を挿入しようとするとSQLITE_FULLエラーが発生して失敗します。

AUTOINCREMENTは、IDが単調増加することを保証するため、これが必要です。