2012-07-15 7 views
20

In sqlite3 faq wird erwähnt, dass ein ganzzahliger Primärschlüssel, der mit einem Nullwert gespeist wird, automatisch inkrementiert würde. Aber das passiert nicht für mich.Kein Autoinkrement für Integer Primärschlüssel in sqlite3

nachzubilden, eine Tabelle in sqlite3, CREATE TABLE dummy(serial_num INTEGER PRIMARY KEY, name TEXT); und füllt sie mit Python,

import sqlite3 as lite 
con = lite.connect('some.db') 
cur=con.cursor() 
data = "someone's name" 
cur.execute("INSERT INTO dummy VALUES(NULL, ?)", data) 
con.commit() 

Das erste Attribut serial_num ist leer dargestellt, während das Namensattribut in Ordnung ist. Wenn ich SELECT serial_num FROM dummy mache, bekomme ich nur ein paar Leerzeichen. Was mache ich falsch?

+0

Ich muss hinzufügen, dass ich erneut versucht, das Schema als '... serial_num INTEGER PRIMARY KEY NOT NULL ...' und erhalten Sie den Fehler 'sqlite3.IntegrityError: dummy.serial_no darf nicht NULL sein – yayu

Antwort

25

Dies ist eine der Eigenheiten von SQLite. Von dem fine manual:

According to the SQL standard, PRIMARY KEY should always imply NOT NULL. Unfortunately, due to a long-standing coding oversight, this is not the case in SQLite. Unless the column is an INTEGER PRIMARY KEY SQLite allows NULL values in a PRIMARY KEY column. We could change SQLite to conform to the standard (and we might do so in the future), but by the time the oversight was discovered, SQLite was in such wide use that we feared breaking legacy code if we fixed the problem.

Die Dokumentation auf INTEGER PRIMARY KEY ist ein wenig unklar, was genau für eine Spalte erforderlich ist, dieser spezielle INTEGER PRIMARY KEY zu sein, dass auto-Schritte, aber die Realität ist, dass die Spalte NOT NULL sein muss wenn Sie den NULL-Wert verwendet werden sollen bedeuten, „geben Sie mir den nächsten automatische Erhöhung Wert“ beim Einfügen:

create table dummy (
    serial_num integer primary key not null, 
    name text 
); 

wenn Sie die not null auslassen, müssen Sie Ihre Einsätze wie dies zu tun:

insert into dummy (name) values (?) 

, um den Auto-Inkrement-Wert für serial_num zu erhalten. Ansonsten hat SQLite keine Möglichkeit, den Unterschied zwischen einem NULL-Wert "gib mir den nächsten Auto-Inkrement-Wert" und einem NULL-Wert "setze einen NULL-Wert in serial_num, weil die Spalte NULL erlaubt" zu sagen.

+1

Vielen Dank. Beim Experimentieren habe ich auch gelernt, dass Autoincrement nur mit einer Spalte als Primärschlüssel funktioniert. – yayu

+0

@yayu: Dieser Teil der [Dokumentation] (http://www.sqlite.org/lang_createtable.html#primikeyconst) ist zumindest ziemlich klar: "Wenn eine Tabelle einen einzelnen Spaltenprimärschlüssel hat und der deklarierte Typ von diese Spalte ist "INTEGER" ... " –

2

Die oben angegebene Syntax zum Einfügen scheint in Abwesenheit von not null nicht zu funktionieren.

Hier ist ein Beispiel - beachten Sie, dass das ID-Feld nicht automatisch inkrementiert wird, obwohl ich das Einfügeformat verwende, das Sie oben angegeben haben.

sqlite> .schema logTable 
CREATE TABLE logTable (ID INTEGER PRIMARY_KEY, ts REAL, level TEXT, message TEXT); 
sqlite> INSERT into LOGTABLE (ts, level, message) VALUES (111, "autoinc test", "autoinc test"); 
sqlite> select * from logtable where ts = 111; 
|111.0|autoinc test|autoinc test 
sqlite> 

Es funktioniert mit der NOT NULL-Problemumgehung.

sqlite> create TABLE logTable (ID INTEGER PRIMARY KEY NOT NULL, ts REAL, level TEXT, message TEXT); 
sqlite> INSERT into LOGTABLE (ts, level, message) VALUES (222, "autoinc test", "autoinc test"); 
sqlite> select * from logtable where ts = 222; 
1|222.0|autoinc test|autoinc test 

Ich entschuldige mich dies als neue Antwort für die Entsendung stattdessen auf der vorherige Antwort zu kommentieren, aber mein Ruf-Score zu niedrig Kommentare zu schreiben, und ich dachte, dass es wichtig wäre, dass die alternativen Insert-Anweisung zu beachten ist, keine angemessene Problemumgehung.

Verwandte Themen