2012-07-15 32 views
20

在sqlite3 faq中,提到了一个被输入空值的整数主键会自动增加。但这不是为我发生的。没有自动增量sqlite3中的Integer主键

复制,表中的sqlite3,CREATE TABLE dummy(serial_num INTEGER PRIMARY KEY, name TEXT);和使用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() 

第一属性SERIAL_NUM正在显示空白而名称属性是好的。当我做SELECT serial_num FROM dummy我只是得到一堆空白。我究竟做错了什么?

+0

我必须补充说,我重试定义架构为'... serial_num INTEGER PRIMARY KEY NOT NULL ...'并得到错误'sqlite3.IntegrityError:dummy.serial_no可能不是NULL' – yayu 2012-07-15 07:11:00

回答

25

这是SQLite的怪癖之一。从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.

INTEGER PRIMARY KEY的文档是有点不清楚什么恰恰需要一列是这个特殊的INTEGER的主键自动递增,但实际情况是,该列必须是NOT NULL如果你想使用NULL值意味着“给我下一个自动递增值”插入时:

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

如果你离开了not null,你需要做的刀片是这样的:

insert into dummy (name) values (?) 

获取serial_num的自动增量值。否则,SQLite无法区分NULL的含义“给我下一个自动增量值”和NULL含义“因为列允许NULL而在serial_num中放置NULL值”。

+1

非常感谢。在进行实验的同时,我也了解到,自动增量仅适用于一列作为主键。 – yayu 2012-07-15 07:30:10

+0

@yayu:[documentation](http://www.sqlite.org/lang_createtable.html#primkeyconst)的那部分至少是很清楚的:“如果一个表有一个单一的主键,并且声明的类型为该列是'INTEGER' ...“ – 2012-07-15 07:34:47

2

上面提供的插入语法在not null不存在的情况下似乎不起作用。

下面是一个示例 - 请注意,即使使用上面指定的插入格式,ID字段也不会自动增加。

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> 

它与NOT NULL解决方法一起工作。

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 

我张贴这是一个新的答案,而不是评论以前的答案道歉,但我的名誉分数太低添加评论,我认为一定要注意交替插入语句是很重要没有一个适当的解决方法。