【问题标题】:Can multiple columns count as one combined primary key?多列可以算作一个组合主键吗?
【发布时间】:2019-02-19 22:50:20
【问题描述】:

有一个村庄,村民们参观了多间房屋。我想存储哪个村民拜访了哪个房子,以及他们多久拜访一次。我决定按如下方式创建表;

CREATE TABLE 'visitis'('villager' TEXT NOT NULL, 'house' INTEGER NOT NULL, 'amount' INTEGER NOT NULL DEFAULT 0);

表格存储如下;

  • villager 存储村民的姓名。每个村民都有一个独特的名字。
  • house 是房子的地址。这是一个整数。
  • amount 存储该村民去过那所房子的次数。

此表不包含主键,因此,我认为不是最佳的。村民的数量和房屋的数量都未定义,以至于将村民或房屋存储​​为列已不再有效。

多行可能包含相同的村民姓名,并且多行可能包含相同的住宅地址。唯一已知的独特性,是村民和房子的组合是独一无二的。因此我想知道是否有一种方法可以将两列用作共享主键。这可以节省大量时间,但我不确定 SQLite 是否能够做到这一点。 如果没有,有没有更好的方法来做到这一点?我有条件;

  1. 大多数村民会参观多个房屋。不过这个数量比较少,可以假设在 50 栋以下;
  2. 有很多房屋(整数)不会被访问。然而,访问过的房屋通常会被多达 10 名村民访问;
  3. 村民会参观数量有限的房屋,只有少数人会参观 1000 多座房屋;
  4. 重要的是要存储哪个村民去过哪个房子的频率;
  5. 需要经常通过村民姓名和房屋地址号码访问数据;
  6. 房屋数量和村民数量都可以很高。

也许我遗漏了一些显而易见的东西。我是……?

【问题讨论】:

  • 嗨。这里唯一的 CK(候选键)是 {villager, house}。如果您决定想要一个,那是唯一可能的 PK。是时候阅读有关信息建模、关系模型和数据库设计的教科书了。 PS这不清楚:“村民数量和房屋数量都未定义到将村民或房屋作为列存储不再有效的程度。”您的意思是通过实施减少字符串存储吗?你知道你已经为每对可能的村民 - 房子描述了一张桌子吗?你想避免这种情况吗?
  • 这是一个常见问题解答。请始终在谷歌上搜索您的问题/问题/目标的许多清晰、简洁和特定的版本/措辞,带和不带您的特定字符串/名称,并阅读许多答案。将您发现的相关关键字添加到搜索中。如果您没有找到答案,请发布,使用一个变体搜索您的标题和关键字作为您的标签。请参阅向下投票箭头鼠标悬停文本。 (例如,使用 'site:Stack Overflow sqlite' 搜索您的标题。)

标签: sqlite primary-key


【解决方案1】:

该表的主键似乎是villagerhouse 列的组合。 SQLite 对包含多于一列的主键没有问题:

CREATE TABLE visitis (
    villager TEXT NOT NULL,
    house INTEGER NOT NULL,
    amount INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY (villager, house)
);

这样做的逻辑原因是访问给定房屋的给定村民只需要由一条记录表示。 amount 列处理可能不止一次访问的情况。

虽然这解决了您的直接问题,但并不理想,因为您的表未标准化。 visitis 表通常被称为联结表,因为它以某种有意义的方式连接其他两个表。这是一个更好的设计:

CREATE TABLE visitis (
    villager_id INTEGER NOT NULL,
    house_id INTEGER NOT NULL,
    amount INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY (villager_id, house_id),
    FOREIGN KEY (villager_id) REFERENCES villages (id),
    FOREIGN KEY (house_id) REFERENCES houses (id)
);

现在我们只保留外键对,每个外键都指向villageshouses 表中的一条记录。这样,我们就不会复制任何数据。

【讨论】:

  • 1NF 以上的归一化用它的投影替换了一个表。它不引入新列。根据常识,问题表在 5NF 中。无法进一步规范化。这种“重复”是一个基于实现的概念,与规范化无关,涉及不“重复”的 id,即使同一位置的其他值将被“重复”,并且用于数据压缩和相关性能。具有讽刺意味的是,减少“重复”会增加冗余。
  • @philipxy 标题问题是SQLite是否支持由多列组成的主键。答案是肯定的,我已经说明了为什么会这样。如果您建议 OP 应该额外存储重复信息,那么您应该解释原因。
  • 该评论与我的评论无关。我的说替代设计不是来自规范化。 (不添加 id。)(或解决插入/删除异常——但如果这是重新设计的一部分,它不合理地假设原始设计是错误的并且它不存储行为 0。)PS您没有说到底要在新表中存储什么,但是一旦我们为村民和房屋提供了单独的表格,我们通常会(可能是非“重复” - 无论是什么)都不会将村民 - 房屋对存储为 0访问,因此 0 似乎是一个有问题的默认值。
猜你喜欢
  • 2018-06-23
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多