SQLite主键在多列上


Answers:


805

根据文档,它是

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);

3
是的,这是正确的,但是根据文档,CREATE TABLE是什么(column1 PRIMARY KEY,column2 PRIMARY KEY);应该也可以,但事实并非如此。
Yar

6
@Yar文档说:“如果单个CREATE TABLE语句中有多个PRIMARY KEY子句,则是错误。” 是的,铁路图可能也表明这是有效的,但是下面的文字阐明了它不是有效的。
Brian Campbell

10
切记像在此答案的末尾添加PRIMARY KEY(column1,column2)部分。如果尝试在column2定义之后添加它,则会出现语法错误
vovahost

159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

主键不强加NOT NULL吗?
pratnala 2014年

23
@pratnala在标准SQL中,是的。在SQLite中,NULL主键中允许。该答案强调,如果您想要更多标准行为,则需要添加NOT NULL自己。我的答案只是多列主键的基本语法。
Brian Campbell

42

是。但是请记住,这样的主键允许NULL两个列中的值多次出现。

这样创建一个表:

    sqlite> CREATE TABLE something (
column1, column2, value, PRIMARY KEY (column1, column2));

现在这可以正常工作而不会发出任何警告:

sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> select * from something;
NULL|NULL|bla-bla
NULL|NULL|bla-bla

有没有提到这种行为的原因?什么是转储数据库中的几行并仍然删除重复项(即使它们包含)的一种好方法NULL
Pastafarianist,2015年

4
@Pastafarianist sqlite.org/lang_createtable.html- “根据SQL标准,PRIMARY KEY始终应表示NOT NULL。不幸的是,由于某些早期版本中存在错误,SQLite并非如此。[...] NULL值被认为与所有其他值(包括其他NULL)不同。”
令人难以置信的

是的,在SQL中,NULL总是比较false。因此,关系理论专门将NULL排除为任何关键组件的值。但是,SQLite是关系实践。看来作者选择了务实地允许使用多个而不是“相等”的键。显然,最好不要将NULL作为键值。
holdenweb

31

基本:

CREATE TABLE table1 (
    columnA INTEGER NOT NULL,
    columnB INTEGER NOT NULL,
    PRIMARY KEY (columnA, columnB)
);

如果您的列是其他表的外键(常见情况):

CREATE TABLE table1 (
    table2_id INTEGER NOT NULL,
    table3_id INTEGER NOT NULL,
    FOREIGN KEY (table2_id) REFERENCES table2(id),
    FOREIGN KEY (table3_id) REFERENCES table3(id),
    PRIMARY KEY (table2_id, table3_id)
);

CREATE TABLE table2 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

CREATE TABLE table3 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

14

主键字段应声明为非null(这是非标准的,因为主键的定义是它必须唯一且不能为null)。但是下面是对任何DBMS中所有多列主键的一种良好做法。

create table foo
(
  fooint integer not null
  ,foobar string not null
  ,fooval real
  ,primary key (fooint, foobar)
)
;

11

从SQLite版本3.8.2开始,显式NOT NULL规范的替代方法是“ WITHOUT ROWID”规范:[ 1 ]

NOT NULL is enforced on every column of the PRIMARY KEY
in a WITHOUT ROWID table.

“ WITHOUT ROWID”表具有潜在的效率优势,因此,可以考虑的一个较简单的选择是:

CREATE TABLE t (
  c1, 
  c2, 
  c3, 
  PRIMARY KEY (c1, c2)
 ) WITHOUT ROWID;

例如,在sqlite3提示符下: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2


对于当今阅读此书的任何人:WITHOUT ROWID都有其他含义,并且不应用作替代编写NOT NULL主键的方法。
Shadowtalker


2

PRIMARY KEY (id, name)没有为我工作。添加约束可以代替工作。

CREATE TABLE IF NOT EXISTS customer (id INTEGER, name TEXT, user INTEGER, CONSTRAINT PK_CUSTOMER PRIMARY KEY (user, id))


1

以下代码创建一个以2列为主键的表在SQLite中。

解:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.