任何人都可以告诉我关系数据库中的表(例如MySQL / SQL SERVER)是否可以没有主键吗?
例如,我可以使用表day_temperature
,在其中注册temperature
和time
。我没有看到为这样一个表创建主键的原因。
答案 0 :(得分:30)
从技术上讲,您可以声明这样的表格。
但是在你的情况下,time
应该是PRIMARY KEY
,因为在同一时间内有不同的温度可能是错误的,并且可能无法同时使用不同的温度。
逻辑上,每个表都应该有一个PRIMARY KEY
,以便您可以区分两个记录。
如果您的数据中没有候选键,只需创建一个代理键(AUTO_INCREMENT
,SERIAL
或数据库提供的任何键。)
没有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)
根据你的回答,我会考虑三种选择:
这两个选项对于检索速度最好,如果您有大量读取但会导致较低的插入率,因为索引也必须更新。
此外,在此考虑基数非常重要,并考虑使用自动递增数字的未来后果。如果您计划进行大量插入操作,那么即使是自动递增的无符号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)和两个字段上的单独索引建立唯一约束。