【问题标题】:What happens if you declare an SQLite column PRIMARY KEY + UNIQUE?如果你声明一个 SQLite 列 PRIMARY KEY + UNIQUE 会发生什么?
【发布时间】:2021-11-24 03:09:48
【问题描述】:

SQLite 的文档说:

UNIQUE 约束类似于 PRIMARY KEY 约束,不同之处在于单个表可以有任意数量的 UNIQUE 约束。

我想知道的是,如果我声明如下:

CREATE TABLE Example (
  id INTEGER PRIMARY KEY UNIQUE);

SQLite 是创建两个索引还是一个?如果我不使用 rowid(即如果列是 id TEXT PRIMARY KEY UNIQUE),行为会有所不同吗?

我意识到最简单的做法就是删除UNIQUE,但我很好奇这会产生什么影响。

【问题讨论】:

  • FWIW,我发现这会创建一个sqlite_autoindex,它会巧妙地改变正常行为。一开始似乎没什么区别,但后来我开始发现我无法通过主键随机选择某些行。我还不能确切地弄清楚这是为什么,所以最好能得到你的问题的正确答案。

标签: sqlite


【解决方案1】:

当您定义一个主键时,它将是唯一的,无需为唯一列定义另一个索引。

【讨论】:

  • 这不能回答问题。
【解决方案2】:

主键的意义在于它们对于任何给定的行都是唯一的。

意味着您可以选择一个或多个字段作为主键,但单个字段不必是唯一的。

另一方面,Unique 对于指定的字段必须是唯一的。 所以它更像是你放置的一个约束。

举个例子:

CREATE TABLE IF NOT EXISTS user2domain (
    userID INTEGER NOT NULL,
    domainID INTEGER NOT NULL,
    PRIMARY KEY (userID, domainID),
    UNIQUE(userID, domainID) ON CONFLICT IGNORE
)

您实际上不必指定唯一约束,因为主键将覆盖相同的字段。

CREATE TABLE IF NOT EXISTS user2domain (
    userID INTEGER NOT NULL,
    domainID INTEGER NOT NULL,
    PRIMARY KEY (userID, domainID)
)

-- add this way
INSERT OR IGNORE INTO user2domain(userID, domainID) VALUES(@userID, @domainID)

这就够了。

当您绝对喜欢任何字段时,请使用 Unique 约束 必须是唯一的,但不一定是行标识符。

预期的行为是覆盖。主要的优先级更高。

【讨论】:

  • 这没有回答问题。这不是你是否应该这样做的问题,而是如果你这样做了会发生什么。
  • 什么也没发生。取决于 sqlite 的实现,但通常是 IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY : SQLITE_CONSTRAINT_UNIQUE ,所以它只创建一个键。
  • 不,这显然是错误的,因为UNIQUE 将创建一个sqlite_autoindex。请参阅我对这个问题的评论。
  • 你能复制这种行为吗?我有最新的sqlite3,我尝试了很多测试,没有效果。当您将它们都放在同一个键上时,可能会发生错误或伪影,但我还不能引起任何奇怪的行为。如果是这样,我们可以将其标记给 sqlite 团队以修复它,因为在这种情况下,预期的行为是主键覆盖唯一键行为。
  • 我一直无法完全诊断问题。删除 UNIQUE 约束修复了它,但我从来没有发现原因,所以我只是重新设计了程序来避免它。 Amyway,这里的相关点是您的回答没有解决问题中提出的任何问题。 OP 并不要求提供有关使用的教程 - 他们想了解底层机制。
猜你喜欢
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 2011-04-20
  • 2017-02-04
  • 1970-01-01
  • 2018-05-01
相关资源
最近更新 更多