主键(PRIMARYKEY)-飞外

(1)一个表只能有一个主键

每个表只能有最多一个主键。具有主键的表中的每一行在其主键列中必须具有唯一的值组合。如果INSERT或UPDATE语句尝试修改表内容,以使两行或更多行具有相同的主键值,则违反约束。

只能有一个主键,并不等同于只能有一列是主键,因为可以定义联合主键。例如:

Create table t1 PRIMARY KEY(A,B)INSERT INTO T1 VALUES (1,1,2)INSERT INTO T1 VALUES (1,2,2)INSERT INTO T1 VALUES (2,1,2)INSERT INTO T1 VALUES (2,2,2)

并不会报错,而如果继续添加下面的语句

INSERT INTO T1 VALUES (1,2,52),则会报错

(2)NULL值主键

按照设计理念,主键应该不能为空值,但早起的SQLITE出了BUG,为了实现向后兼容,SQLITE最终确定了,主键允许NULL值。为了确定主键值的唯一性,将NULL值视为与所有其他值(包括其他NULL)不同。


(3)ROWID

未定义主键的表,默认有一个隐藏的主键:rowid,并且rowid还有另两个别名 OID 和 _ROWID_ 。

这个ROWID和定义的唯一性主键不冲突,并不占用主键定义的 名额 。同样是上一个表,添加rowid的显示结果如下:


ROWID是个64位的有符号整数,从1开始自动增长。可以指定ROWID进行删除。


(4)WITHOUT ROWID

当创建表时,最后添加了WITHOUT ROWID语句,则强制不创建ROWID列。

但没有ROWID的表,则必须创建主键。例如:


(5)integer primary key

当一个表没有使用 without rowid ,并且设置了单列 integer primary key ,则这个单列相当于ROWID的显示别名,请看下图的例子,当插入a=0的行时,ROWID也并没有自动变为4,也成了0


上面提到的例外是,如果声明类型为 INTEGER 的列的声明包含 PRIMARY KEY DESC 子句,则它不会成为rowid的别名,也不会归类为整数主键。 这个怪癖不是故意的。 这是由于早期SQLite版本中的错误所致。 但是修复该错误可能会导致向后不兼容。 因此,原始行为得以保留(并记录在案),因为在极端情况下的奇怪行为要比兼容性破坏要好得多。 这意味着以下三个表声明都使 x 列成为rowid(整数主键)的别名:

CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z);CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x ASC));CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC));

而下面的语句却不会:

CREATE TABLE t(x INTEGER PRIMARY KEY DESC, y, z);

作为ROWID的别名列,是不允许空值的,如果未能成为ROWID的别名列,则可以是空值,例如: