ChatGPT解决这个技术问题 Extra ChatGPT

多列上的 Sqlite 主键

在 SQLITE 中的多于 1 列上指定主键的语法是什么?

这也称为复合键 en.wikipedia.org/wiki/Compound_key
@OneWorld 或复合键,如果任何列本身不是键。

B
Brian Campbell

根据 documentation,它是

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

嗯,这是对的,但是根据文档,CREATE TABLE something (column1 PRIMARY KEY, column2 PRIMARY KEY);应该也是可能的,但事实并非如此。
@Yar 文档说“如果在单个 CREATE TABLE 语句中有多个 PRIMARY KEY 子句,那就是错误。”是的,铁路图可能表明这也是有效的,但下面的文字说明它不是。
请记住在此答案的末尾添加 PRIMARY KEY(column1, column2) 部分。如果您尝试在 column2 定义之后添加它,您将收到语法错误。
C
Czechnology
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

主键不会强加一个 NOT NULL 吗?
@pratnala 在标准 SQL 中,是的。在 SQLite 中,主键中允许使用 NULL。此答案强调,如果您想要更标准的行为,则需要自己添加 NOT NULL。我的答案只是多列主键的非常基本的语法。
D
Deepzz

是的。但请记住,这样的主键允许两列中的 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 sqlite.org/lang_createtable.html - “根据 SQL 标准,PRIMARY KEY 应始终暗示 NOT NULL。不幸的是,由于某些早期版本中的错误,SQLite 中并非如此。[...] NULL 值被认为是不同的来自所有其他值,包括其他 NULL。”
是的,在 SQL 中,NULL 总是比较假。正因为如此,关系理论明确排除了 NULL 作为任何关键组件的值。然而,SQLite 是关系实践。似乎作者选择务实地允许多个但不是“相等”的键。显然,最好不要将 NULL 作为键值。
c
compte14031879

基本的 :

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
);

W
Waynn Lue

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

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

p
peak

从 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 的替代方法。
S
Slava Rozhnev

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

解决方案:

CREATE TABLE IF NOT EXISTS users (
    id TEXT NOT NULL, 
    name TEXT NOT NULL, 
    pet_name TEXT, 
    PRIMARY KEY (id, name)
)

C
Community

另外,您还可以将两列主键设为unique自动增量键设为primary。就像这样:https://stackoverflow.com/a/6157337


这正是我要寻找的。谢谢!
S
Slava Rozhnev

PRIMARY KEY (id, name) 对我不起作用。添加约束代替了这项工作。

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