数据库表可以没有主键吗?

时间:2010-03-25 12:53:55

标签: mysql sql-server database

任何人都可以告诉我关系数据库中的表(例如MySQL / SQL SERVER)是否可以没有主键吗?

例如,我可以使用表day_temperature,在其中注册temperaturetime。我没有看到为这样一个表创建主键的原因。

12 个答案:

答案 0 :(得分:30)

从技术上讲,您可以声明这样的表格。

但是在你的情况下,time应该是PRIMARY KEY,因为在同一时间内有不同的温度可能是错误的,并且可能无法同时使用不同的温度。

逻辑上,每个表都应该有一个PRIMARY KEY,以便您可以区分两个记录。

如果您的数据中没有候选键,只需创建一个代理键(AUTO_INCREMENTSERIAL或数据库提供的任何键。)

没有PRIMARY KEY的唯一理由是日志或类似的表,它是一个重DML的主题,并且有一个索引将影响超出容忍水平的性能。

答案 1 :(得分:25)

总是取决于

没有来拥有主键。 更重要正确索引。在数据库引擎上取决于主键如何影响索引(即为主键列/列创建唯一索引)。

但是,在你的情况下(以及99%的其他情况),我会添加一个新的自动增量唯一列,如temp_id,并使其成为代理主键。

使得更容易维护此表 - 例如查找和删除记录(即重复的记录) - 并相信我 - 每个表都有时间来解决问题:(。

答案 2 :(得分:11)

主键自然不是时候吗?你会在一定时间内有多个温度吗?

要问的一个更好的问题是,“为什么你会在没有主键的情况下创建一个

答案 3 :(得分:5)

如果有重复条目(例如同一时间)的可能性不是问题,并且您不希望查询特定记录或记录范围,则可以不使用任何类型的密钥。

答案 4 :(得分:5)

您不需要PK,但建议您拥有PK。这是识别唯一行的最佳方式。有时你不需要自动增量int PK,而是在其他东西上创建PK。例如,在您的情况下,如果每次只有一个唯一的行,您应该在时间上创建PK。它可以更快地根据时间进行查找,并确保它们是唯一的(您可以确保不会违反数据完整性):

答案 5 :(得分:1)

我会包含一个代理/自动增量键,特别是如果有可能重复时间/温度读数。您没有其他方法可以唯一标识重复的行。

答案 6 :(得分:0)

时间将成为您的主键。它将帮助索引该列,以便您可以根据日期范围查询数据。 PK最终会使您的行唯一,因此在您的示例中,日期时间是PK。

答案 7 :(得分:0)

我在其中一张桌子上遇到了同样的问题。

问题是PK应该由表的所有行组成,但是这意味着每次插入行时表的大小会非常快。

我选择没有PK,但只在我查找的行上有一个索引。

答案 8 :(得分:0)

在mysql上复制数据库时,没有主键的表可能会导致复制延迟。

http://lists.mysql.com/mysql/227217

  

使用ROW或MIXED时最常见的错误是失败   验证您要复制的每个表都有一个PRIMARY KEY   它。这是一个错误,因为当一个ROW事件(如一个   上面记录的)被发送到奴隶,而不是主人的副本   表的奴隶副本也没有PRIMARY KEY,   没有办法轻松识别您想要的唯一行   复制要改变。

答案 9 :(得分:0)

根据你的回答,我会考虑三种选择:

  • 在两个col上放置PK,这样每次只有一个temp,反之亦然。该解决方案允许具有相同温度或相同时间的多行,只是不存在具有相同温度和时间的任何两行。
  • 根本没有放置PK,但确实在两个cols上放了一个唯一的索引。一个包含cols的唯一索引。这将允许临时和时间中的空值,但需要更多空间来维护索引。

这两个选项对于检索速度最好,如果您有大量读取但会导致较低的插入率,因为索引也必须更新。

  • 根本不放任何索引,也不放PK。这对于插入来说是最好的,但对于搜索非常糟糕。用于记录由另一个人完成检索的日志 机制或当不需要插入设备来检查重复时。

此外,在此考虑基数非常重要,并考虑使用自动递增数字的未来后果。如果您计划进行大量插入操作,那么即使是自动递增的无符号bigint也会有风险,因为它最终会耗尽。在您的示例中,我猜您每天都会保存数据 - 持续多长时间?如果你每分钟都节省一点温度就会有问题......所以我将此作为一个极端的例子。

我想最好从表中考虑你需要什么。你在做什么"省去,忘了"整个一年的每一分钟的温度?你是否经常在你的业务逻辑中实时决策使用这个表?我认为最好将实时(oltp)所需的数据与很少需要的长期保存数据进行隔离,并且允许其检索延迟很高(olap)。它甚至值得将数据复制到两个不同的表中,一个重度索引并偶尔擦除以控制基数,第二个实际上保存在几乎没有索引的magentic磁盘上(可以传输从主fs到另一个fs的模式。)

答案 10 :(得分:0)

即使您没有在MySQL中向InnoDB表添加主键,MySQL也会向该表添加隐藏的聚集索引。如果未定义主键,则MySQL会在所有键列都不为空的情况下找到第一个UNIQUE索引,并且InnoDB会将其用作聚集索引。

如果表没有主键或合适的UNIQUE索引,则InnoDB在包含行ID值的综合列上内部生成聚集索引GEN_CLUST_INDEX。

https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

答案 11 :(得分:-5)

我有一个不需要主键的表的更好示例 - 一个木匠表。假设我有一个名为“capabilities”的表,另一个名为“groups”的表,我想要一个joiner表,告诉我所有组可能具有的所有功能,所以它是基本的

create table capability_group
(  capability_id varchar(32),
    group_id     varchar(32));

没有理由拥有主键,因为您从不处理单行 - 您要么想要给定组的所有功能,要么要求给定功能的所有组。最好对(capabilty_id,group_id)和两个字段上的单独索引建立唯一约束。