sqliteに自動インクリメントはありますか?


109

私は自動インクリメントを持つテーブルを作成しようとしていますprimary keysqlite3の。これが本当に可能かどうかはわかりませんが、他のフィールドを指定するだけでいいのですが。

例えば:

CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));

それから、値を追加するとき、私はしなければならないことだけを望んでいました:

INSERT INTO people
VALUES ("John", "Smith");

これは可能ですか?

Windows 7で実行sqlite3cygwinています。

回答:


166

ROWIDと呼ばれる無料で入手できます。これは、要求してもしなくても、すべてのSQLiteテーブルにあります。

タイプINTEGER PRIMARY KEYの列を組み込む場合、その列は自動ROWID列を指します(別名)。

ROWID(それを呼び出す名前は何でもかまいません)は、期待どおりに行を挿入するたびに値が割り当てられます。INSERTで非NULL値を明示的に割り当てると、自動インクリメントではなく、指定された値が取得されます。INSERTでNULLの値を明示的に割り当てると、次の自動インクリメント値が取得されます。

また、次のことは避けてください。

 INSERT INTO people VALUES ("John", "Smith");

そして使う

 INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");

代わりに。最初のバージョンは非常に脆弱です。テーブル定義で列を追加、移動、または削除した場合、INSERTは失敗するか、誤ったデータ(誤った列の値)が生成されます。


53
SAME値は複数回生成される可能性があるため、ROWIDは実際の自動インクリメントとはまったく異なります。たとえば、空のテーブルで3行を挿入すると、3行目にROWIDとして3が期待どおりに与えられます。ただし、2つの行を挿入し、最後の行を削除して別の行を挿入し、2番目の行と同じように、3番目に挿入された行にROWID 2を指定します。したがって、削除が発生し、削除またはROWIDのNULL化が関連するテーブルでも実行されないテーブル内のROWIDをテーブルが参照する場合、明らかに深刻な問題があります。
Nick

10
答えから明らかでない場合は、選択ステートメントでROWIDを使用できます。例:select rowid from people;
Colin D

@Nickはあなたのアイデアを補完するだけです。自動インクリメントは安全対策です。また、ROWIDで2つの行が衝突することについて話しているのではありません。
YoussefDir

68

はい、可能です。SQLite FAQによると:

宣言INTEGER PRIMARY KEYされた列は自動インクリメントされます。


12
Ukuによって言及され、ドキュメントでも説明されているように、これが機能するためには、IDにNULLを渡す必要があるという警告があります。
Matt Hulse、2011年

22
NULLを使用する必要があるのは、INSERTする列のリストを省略した場合のみです。これは決して良い方法ではありません。列を指定する場合、自動インクリメント列を省略するだけで、次の値を受け取ります。
Larry Lustig、2011年

5
別の注意点:上記とまったく同じように「INTEGER ...」を記述します。省略形の「INT ...」は機能しません。
Marcin Wojnarski

26

本日現在-2018年6月


これは、SQLiteの公式ドキュメントでこの件について述べていることです(太字と斜体は私のものです)。

  1. AUTOINCREMENTキーワード課し余分なCPU、メモリ、ディスク容量、およびディスクI / Oのオーバーヘッドと厳密に必要でない場合は避けるべきです。通常は必要ありません。

  2. SQLiteでは、タイプINTEGER PRIMARY KEYのROWID(WITHOUT ROWIDテーブルを除く)のエイリアスであり、常に64ビットの符号付き整数です。

  3. INSERTでは、ROWIDまたはINTEGER PRIMARY KEY列に 明示的に値が指定されてい ない場合、未使用の整数が 自動的に入力されます通常現在使用されている最大のROWIDよりも1大きい整数です。これは、AUTOINCREMENTキーワードが使用されているかどうかに関係なく当てはまります。

  4. INTEGER PRIMARY KEYの後にAUTOINCREMENTキーワードが表示される場合は、自動ROWID割り当てアルゴリズムが変更され、データベースの存続期間中の ROWID の再利用防止されます。つまり、AUTOINCREMENTの目的は、以前に削除された行からのROWIDの再利用を防ぐことです。


11

これ読んだ?AUTOINCREMENTフィールドを作成するにはどうすればよいですか。

INSERT INTO people
VALUES (NULL, "John", "Smith");

だからあなたが言っていることは私がやろうとしていることは不可能であるということですが、私は一種のシミュレーションをすることができます。挿入でnullを使用する必要がありますか?
ewok、2011年

1
何もする必要はありませんが、常にIDとしてNULLを挿入します。それは、sqliteが内部でどのようにそれを行うかを説明するだけです。
Uku Loskit

7
INSERTでのNULLは、INSERT する列のリストを指定しない場合にのみ必要です(この場合、列の数と正確に一致するいくつかの値が必要であり、プレースホルダーとしてNULLを使用する必要があります)。ただし、列のリストを指定せずにINSERTを実行することは決して良い習慣ではありません。列のリストを指定する場合は、自動インクリメント列とNULL値の両方を省略すれば、期待どおりの結果が得られます。
Larry Lustig、2011年

4

AUTOINCREMENT近くのキーワードを指定しないでくださいPRIMARY KEY。自動インクリメントの主キーを作成して挿入する例:

$ sqlite3 ex1

CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);

INSERT INTO room(name, home_id) VALUES ('test', 'home id test');

INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');

SELECT * FROM room;

あげる:

1|test|home id test
2|test 2|home id test 2

4

ROWIDのほかに、独自の自動インクリメントフィールドを定義できますが、お勧めしません。自動的に増加するROWIDを使用する場合は、常により良いソリューションです。

このAUTOINCREMENTキーワードは、追加のCPU、メモリ、ディスク領域、およびディスクI / Oオーバーヘッドを課すため、厳密に必要でない場合は回避する必要があります。通常は必要ありません。

詳細については、こちらをお読みください。


どうやらROWIDは常に自動的に増加するわけではありません。ニックのコメントを参照してください
rogerdpack

1
違います。自動インクリメントは、IDを再利用しないため、いくつかの点で優れています。これは、多くのシステムにとって非常に重要な要件です。
O'Rooney

3

SQLite AUTOINCREMENTは、テーブル内のフィールドの値を自動インクリメントするために使用されるキーワードです。自動インクリメントする特定の列名でテーブルを作成するときに、AUTOINCREMENTキーワードを使用してフィールド値を自動インクリメントできます。

キーワードAUTOINCREMENTは、INTEGERフィールドでのみ使用できます。構文:

AUTOINCREMENTキーワードの基本的な使用法は次のとおりです。

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

例以下を参照:COMPANYテーブルを次のように作成することを検討してください。

sqlite> CREATE TABLE TB_COMPANY_INFO(
   ID INTEGER PRIMARY KEY   AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

次に、以下のレコードをテーブルTB_COMPANY_INFOに挿入します。

INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );

レコードを選択してください

SELECT *FROM TB_COMPANY_INFO
ID      NAME            AGE     ADDRESS             SALARY
1       Manoj Kumar     40      Meerut,UP,INDIA     200000.00

2

私はこの答えが少し遅れていることを知っています。
この回答の私の目的は、SQLiteでこの種の課題に現在または将来直面し、困難に直面した場合の参考にすることです。

さて、クエリを振り返ると、次のようになります。

CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));

それは私の側で動作します。そのようです、

ここに画像の説明を入力してください

SQLiteを使用している場合に備えて、DBite for SQLiteを確認することをお勧めします。さまざまなプラットフォームでも動作します。


0

あなたがすることは正しいですが、「自動インクリメント」の正しい構文はスペースなしでなければなりません:

CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);

(私はあなたのvarcharを文字列に変更したことにも注意してください。SQLiteが内部的にvarcharを文字列に変換するので、なぜわざわざですか?)

次に、挿入はSQL言語で可能な限り標準にする必要があります。

INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');

idを省略した場合、自動的にインクリメントされて割り当てられることは事実ですが、私は個人的には将来変更される可能性のある自動メカニズムに依存しないことを好みます。

自動インクリメントに関する注意:多くの指摘がありましたが、SQLiteの人々には推奨されていませんが、自動インクリメントが使用されていない場合に、削除されたレコードのIDを自動的に再利用することは好きではありません。言い換えると、削除されたレコードのIDが二度と表示されないことを気に入っています。

HTH


この点で、オルーニーの発言を完全に共有します。
Luca Nanetti、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.