(1)一个表只能有一个主键
每个表只能有最多一个主键。具有主键的表中的每一行在其主键列中必须具有唯一的值组合。如果INSERT或UPDATE语句尝试修改表内容,以使两行或更多行具有相同的主键值,则违反约束。
只能有一个主键,并不等同于只能有一列是主键,因为可以定义联合主键。例如:
Create table t1
(a,
B,
C,
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的别名列,则可以是空值,例如:
如下面所示,A列明显未能成为ROWID的别名。