这看起来像是一个副本,即使我问它,但我搜索,没有找到它.这似乎是一个很好的问题,尽管我相信我可以在很多博客上找到它.所以你会有比你在博客上能看到的更多的辩论.

我遇到了一个问题:获取太多记录.我认为这是"扩张".我在连接集合中添加了一个表,行数被扩展了,太多了.通常情况下,当发生这种情况时,我会 Select 连接中涉及的所有ID字段.这样一来,扩展发生的地方就非常明显了,我可以更改连接的ON来修复它.除此之外,我添加的表没有ID字段.对我来说,这是个问题.但也许我错了.

问题是:数据库中的每个表都应该有一个用作PK的标识字段吗?在每个表中都有ID字段有什么缺点吗?如果你有理由确定这个表永远不会用于PK/FK关系,那该怎么办?

相关但不重复:When having an identity column is not a good idea?

显然,这场辩论已经进行了going on for a while次.应该知道.

This post(代理与自然关键点)也很重要.

推荐答案

有两个概念很接近,但不应混淆:IDENTITYPRIMARY KEY

每个表(除了罕见的情况)都应该有一个PRIMARY KEY,这是唯一标识一行的一个值或一组值.

请参阅here了解原因.

IDENTITYSQL Server中某列的属性,这意味着该列将自动填充递增值.

由于此属性的性质,此列的值本质上是UNIQUE.

然而,在IDENTITY列上不会自动创建UNIQUE约束或UNIQUE索引,并且在发出SET IDENTITY_INSERT ON之后,可以在IDENTITY列中插入重复的值,除非它受到明确的UNIQUE约束.

IDENTITY列不一定是PRIMARY KEY,但通常用于填充替代项PRIMARY KEY

在任何特定情况下,它可能有用,也可能无用.

因此,你的问题的答案是:

问题是:数据库中的每个表都应该有一个用作PK的标识字段吗?

这是:

No. There are cases when a database table should NOT have an IDENTITY field as a PRIMARY KEY.

在我脑海中出现了三种情况,当IDENTITY作为PRIMARY KEY不是最好的主意时:

  • 如果你的PRIMARY KEY是复合的(比如在多对多链接表中)
  • 如果你的PRIMARY KEY是自然的(比如州代码)
  • 如果PRIMARY KEY在数据库中是唯一的(在本例中,使用GUID/UUID/NEWID)

所有这些情况都意味着以下情况:

You shouldn't have IDENTITY when you care for the values of your PRIMARY KEY and explicitly insert them into your table.

Update:

多对多链接表与它们链接的表之间应该有一对id,作为复合键.

这是一个自然的复合密钥,您已经必须使用它(并设置为UNIQUE),因此没有必要为此生成代理密钥.

我不明白你为什么要从任何其他表中引用一个many-to-many链接的表,除了它们链接的表,但是假设你有这样的需求.

在这种情况下,只需通过复合键引用链接表.

此查询:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (a_id, b_id, PRIMARY KEY (a_id, b_id))
CREATE TABLE business_rule (id, a_id, b_id, FOREIGN KEY (a_id, b_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a
ON      a.id = br.a_id

比这个更有效:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (id, a_id, b_id, PRIMARY KEY (id), UNIQUE KEY (a_id, b_id))
CREATE TABLE business_rule (id, ab_id, FOREIGN KEY (ab_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a_to_b ab
ON      br.ab_id = ab.id
JOIN    a
ON      a.id = ab.a_id

,原因显而易见.

Sql相关问答推荐

判断Pyspark生成的SQL查询

基于前面行的值:当x&>2时重复1,当连续3行x=0时则重复0

不可能在SQL MERGE子句中引发异常

为表中每个缺少的引用创建新行

将主表与历史表连接以获取主表的当前汇率以及历史表中的上一个和最后一个汇率

按每天的最大值分组

正在try 从SQL获取最新的ID和一个唯一名称

Redshift PL/pgSQL循环中的参数化列名

如何计算给定日期前三个月的值以及月初数据?

将FLOAT转换为VARBINARY,然后再转换回FLOAT

Oracle PL/SQL:解决DBMS输出大小限制的问题

根据时间值提取记录

AdventureWorks 查询

复制SQL Server临时表

避免在SQL中使用具有相同条件的多个子查询

按所选的值将记录分组到不同的列中

PostgreSQL中如何提取以特定字符开头的字符串中的所有单词?

Clob 问题 - 将 clob 列拆分为多行

如何在 PL/SQL 中区分返回的 XML 值?

从 JSON 数组中移除对象