22

在 sqlite3 faq中,提到了输入空值的整数主键将自动递增。但这对我来说并没有发生。

在 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 显示为空白,而 name 属性很好。当我这样做时,SELECT serial_num FROM dummy我只会得到一堆空白。我究竟做错了什么?

4

2 回答 2

28

这是 SQLite 的怪癖之一。来自精美手册

根据 SQL 标准,PRIMARY KEY 应始终暗示 NOT NULL。不幸的是,由于长期的编码疏忽,SQLite 并非如此。除非该列是 INTEGER PRIMARY KEY SQLite 允许在 PRIMARY KEY 列中使用 NULL 值。我们可以更改 SQLite 以符合标准(我们将来可能会这样做),但是当疏忽被发现时,SQLite 已被广泛使用,以至于如果我们解决了问题,我们担心会破坏遗留代码。

关于INTEGER PRIMARY KEY的文档有点不清楚列需要什么才能成为这个自动递增的特殊 INTEGER PRIMARY KEY 但实际情况是,如果您想使用 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”。

于 2012-07-15T07:16:02.360 回答
3

上面提供的插入语法在没有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

对于将其发布为新答案而不是评论先前的答案,我深表歉意,但我的声誉得分太低而无法添加评论,我认为重要的是要注意备用插入语句不是一个足够的解决方法。

于 2016-01-10T06:53:21.907 回答