Gibt es ein automatisches Inkrement in SQLite?

109

Ich versuche, eine Tabelle mit einer automatischen Inkrementierung primary keyin Sqlite3 zu erstellen . Ich bin mir nicht sicher, ob dies wirklich möglich ist, aber ich hoffe, nur die anderen Bereiche benennen zu müssen.

Beispielsweise:

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

Wenn ich dann einen Wert hinzufügte, hatte ich gehofft, nur Folgendes tun zu müssen:

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

Ist das überhaupt möglich?

Ich laufe sqlite3unter cygwinWindows 7.

ewok
quelle

Antworten:

166

Sie erhalten eine kostenlose namens ROWID. Dies ist in jeder SQLite-Tabelle enthalten, unabhängig davon, ob Sie danach fragen oder nicht.

Wenn Sie eine Spalte vom Typ INTEGER PRIMARY KEY einfügen, zeigt diese Spalte auf die automatische ROWID-Spalte (ist ein Alias ​​für diese).

ROWID (wie auch immer Sie es nennen) wird ein Wert zugewiesen, wenn Sie eine Zeile einfügen, wie Sie es erwarten würden. Wenn Sie INSERT explizit einen Nicht-NULL-Wert zuweisen, wird dieser angegebene Wert anstelle des automatischen Inkrements abgerufen. Wenn Sie beim EINFÜGEN explizit den Wert NULL zuweisen, wird der nächste Wert für die automatische Inkrementierung angezeigt.

Außerdem sollten Sie versuchen, Folgendes zu vermeiden:

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

und verwenden

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

stattdessen. Die erste Version ist sehr fragil. Wenn Sie jemals Spalten in Ihrer Tabellendefinition hinzufügen, verschieben oder löschen, schlägt INSERT entweder fehl oder erzeugt falsche Daten (mit den Werten in den falschen Spalten).

Larry Lustig
quelle
53
ROWID ist nicht ganz dasselbe wie eine echte automatische Inkrementierung, da der gleiche Wert möglicherweise mehrmals generiert wird. Wenn Sie beispielsweise bei einer leeren Tabelle 3 Zeilen einfügen, erhält die 3. Zeile erwartungsgemäß eine ROWID von 3. Fügen Sie jedoch 2 Zeilen ein, löschen Sie die letzte und fügen Sie eine weitere ein, und geben Sie der 3. eingefügten Zeile eine ROWID von 2, genau wie in der 2. Zeile. Es besteht daher ein offensichtliches ernstes Problem, wenn Tabellen auf ROWIDs in einer Tabelle verweisen, in der Löschvorgänge auftreten und in denen Löschvorgänge oder ROWID-Nullungen nicht auch in den zugehörigen Tabellen durchgeführt werden.
Nick
10
Falls dies aus der Antwort nicht ersichtlich ist, können Sie ROWID in Ihrer select-Anweisung verwenden, z. B.select rowid from people;
Colin D
@Nick, nur um Ihre Idee zu ergänzen: Das automatische Inkrementieren ist also eine Sicherheitsmaßnahme. Und wir sprechen nicht von zwei Zeilen, die in ROWID kollidieren.
YoussefDir
68

Ja, das ist möglich. Laut den SQLite-FAQ :

Eine deklarierte Spalte INTEGER PRIMARY KEYwird automatisch inkrementiert.

Matt Hulse
quelle
12
Die Einschränkung, wie von Uku erwähnt und auch in der Dokumentation erläutert, besteht darin, dass Sie eine NULL für die ID übergeben müssen, damit dies funktioniert.
Matt Hulse
22
Sie benötigen einen NULL zu verwenden , wenn Sie die Liste der Spalten zu INSERT auslassen - nie eine gute Praxis. Wenn Sie die Spalten angeben, können Sie die Spalte für die automatische Inkrementierung einfach weglassen und sie erhält den nächsten Wert.
Larry Lustig
5
Noch eine Einschränkung: Schreiben Sie "INTEGER ..." genau wie oben angegeben. Eine Kurzform "INT ..." funktioniert NICHT.
Marcin Wojnarski
26

Stand heute - Juni 2018


Hier ist, was die offizielle SQLite-Dokumentation zu diesem Thema zu sagen hat (fett und kursiv sind meine):

  1. Das Schlüsselwort AUTOINCREMENT verursacht zusätzlichen CPU-, Speicher-, Speicherplatz- und E / A-Overhead und sollte vermieden werden, wenn es nicht unbedingt benötigt wird. Es wird normalerweise nicht benötigt.

  2. In SQLite ist eine Spalte vom Typ INTEGER PRIMARY KEY ein Alias ​​für die ROWID (außer in WITHOUT ROWID-Tabellen), bei der es sich immer um eine 64-Bit-Ganzzahl mit Vorzeichen handelt.

  3. Wenn bei einem INSERT der Spalte ROWID oder INTEGER PRIMARY KEY kein expliziter Wert zugewiesen wird, wird sie automatisch mit einem Wert gefüllt nicht verwendeten Ganzzahl , normalerweise eine mehr als die größte derzeit verwendete ROWID . Dies gilt unabhängig davon, ob das Schlüsselwort AUTOINCREMENT verwendet wird oder nicht.

  4. Wenn das Schlüsselwort AUTOINCREMENT nach INTEGER PRIMARY KEY angezeigt wird, wird der automatische ROWID-Zuweisungsalgorithmus geändert, um die Wiederverwendung von ROWIDs über die Lebensdauer der Datenbank zu verhindern. Mit anderen Worten, der Zweck von AUTOINCREMENT besteht darin, die Wiederverwendung von ROWIDs aus zuvor gelöschten Zeilen zu verhindern.


quelle
11

Hast du das gelesen Wie erstelle ich ein AUTOINCREMENT-Feld?

INSERT INTO people
VALUES (NULL, "John", "Smith");
Uku Loskit
quelle
Sie sagen also, dass das, was ich versuche, nicht möglich ist, aber ich kann es irgendwie simulieren. Ich muss eine Null in der Einfügung verwenden?
Ewok
1
Sie müssen nichts tun, sondern immer NULL als ID einfügen. Es wird nur erklärt, wie SQLite dies intern tut.
Uku Loskit
7
Der NULL-Wert für INSERT ist nur erforderlich, wenn Sie die Liste der Spalten für INSERT nicht angeben (in diesem Fall benötigen Sie eine Anzahl von Werten, die genau mit der Anzahl der Spalten übereinstimmen, und müssen NULL als Platzhalter verwenden). Ein INSERT ohne Angabe der Spaltenliste ist jedoch niemals eine gute Vorgehensweise. Wenn Sie die Liste der Spalten angeben, lassen Sie einfach sowohl die Spalte für die automatische Inkrementierung als auch den Wert für NULL weg, und Sie erhalten das erwartete Ergebnis.
Larry Lustig
4

Man sollte kein AUTOINCREMENTSchlüsselwort in der Nähe angeben PRIMARY KEY. Beispiel für das Erstellen eines Primärinkrementierungs-Primärschlüssels und das Einfügen von:

$ 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;

wird geben:

1|test|home id test
2|test 2|home id test 2
Denis Kutlubaev
quelle
4

Neben der Zeilen-ID können Sie ein eigenes Feld für die automatische Inkrementierung definieren, dies wird jedoch nicht empfohlen. Es ist immer eine bessere Lösung, wenn wir eine Rowid verwenden, die automatisch erhöht wird.

Das AUTOINCREMENTSchlüsselwort verursacht zusätzlichen CPU-, Speicher-, Speicherplatz- und E / A-Overhead und sollte vermieden werden, wenn es nicht unbedingt benötigt wird. Es wird normalerweise nicht benötigt.

Lesen Sie hier für detaillierte Informationen.

sonvx
quelle
anscheinend wird die Rowid nicht immer automatisch erhöht, siehe den Kommentar von Nick
Rogerdpack
1
Nicht wahr. Das automatische Inkrementieren ist in mancher Hinsicht besser, da IDs nicht wiederverwendet werden - eine ziemlich wichtige Voraussetzung für viele Systeme.
O'Rooney
3

SQLite AUTOINCREMENT ist ein Schlüsselwort, mit dem ein Wert eines Felds in der Tabelle automatisch erhöht wird. Wir können einen Feldwert mithilfe des Schlüsselworts AUTOINCREMENT automatisch erhöhen, wenn Sie eine Tabelle mit einem bestimmten Spaltennamen erstellen, um sie automatisch zu erhöhen.

Das Schlüsselwort AUTOINCREMENT kann nur mit dem Feld INTEGER verwendet werden. Syntax:

Die grundlegende Verwendung des Schlüsselworts AUTOINCREMENT lautet wie folgt:

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

Beispiel siehe unten: Betrachten Sie die zu erstellende COMPANY-Tabelle wie folgt:

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

Fügen Sie nun folgende Datensätze in die Tabelle TB_COMPANY_INFO ein:

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

Wählen Sie nun den Datensatz aus

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

Ich weiß, dass diese Antwort etwas spät ist.
Mein Zweck für diese Antwort ist, dass jeder darauf zurückgreifen kann, ob er jetzt oder in Zukunft mit SQLite auf diese Art von Herausforderung stößt und es ihm schwer fällt.

Wenn Sie nun auf Ihre Anfrage zurückblicken, sollte es ungefähr so ​​sein.

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

Es funktioniert an meinem Ende. Wie so,

Geben Sie hier die Bildbeschreibung ein

Nur für den Fall, dass Sie mit SQLite arbeiten, empfehle ich Ihnen, den DB Browser für SQLite zu testen . Funktioniert auch auf verschiedenen Plattformen.

Kent Aguilar
quelle
0

Was Sie tun, ist korrekt, aber die korrekte Syntax für 'Auto Inkrement' sollte ohne Leerzeichen sein:

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

(Bitte beachten Sie auch, dass ich Ihre Varchars in Strings geändert habe. Das liegt daran, dass SQLite einen Varchar intern in einen String umwandelt. Warum also die Mühe machen?)

Dann sollte Ihre Einfügung so standardmäßig wie möglich in der SQL-Sprache sein:

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

Wenn Sie die ID weglassen, wird sie zwar automatisch erhöht und zugewiesen, aber ich persönlich bevorzuge es, mich nicht auf automatische Mechanismen zu verlassen, die sich in Zukunft ändern könnten.

Ein Hinweis zum automatischen Inkrementieren: Obwohl es, wie viele betonten, von SQLite-Leuten nicht empfohlen wird, mag ich die automatische Wiederverwendung von IDs gelöschter Datensätze nicht, wenn das automatische Inkrementieren nicht verwendet wird. Mit anderen Worten, ich mag es, dass die ID eines gelöschten Datensatzes nie wieder angezeigt wird.

HTH

Luca Nanetti
quelle
In dieser Hinsicht teile ich voll und ganz, was O'Rooney sagt.
Luca Nanetti