为什么使用 int 作为查找表的主键?

Jac*_*ers 30 sql-server primary-key

我想知道为什么我应该使用 int 作为查找表的主键,而不是仅仅使用查找值作为主键(在大多数情况下是一个字符串)。

我知道使用 nvarchar(50) 而不是 int 会使用更多的空间,如果它链接到一个有很多记录的表。

另一方面,直接使用查找值基本上可以避免我们进行连接。我可以想象,如果总是需要加入,这将是一个很大的节省(我们正在开发一个网络应用程序,所以这很重要)。

除了“标准操作”之外,使用 int 主键(特别是对于查找表)有什么优势?

Gai*_*ius 23

您的问题的答案是合乎逻辑的,而不是物理上的 - 您查找的值可能会因业务原因而改变。例如,如果您按电子邮件地址索引客户,当电子邮件地址更改时会发生什么?显然,这不适用于您的所有查找表,但在整个应用程序中以相同方式执行此操作的好处是它使您的代码更简单。如果一切都是整数 → 内部整数关系,你就被覆盖了。

只需阅读您对 Sandy 的评论 - 也许在这种情况下,您真正​​想要的是Check Constraint,而不是外键/查找表,例如:

create table icecream (flavour varchar(10))
go
alter table icecream add constraint ck_flavour check (flavour in ('Orange', 'Pista', 'Mango'))
go
insert into icecream (flavour) values ('Orange')
go
insert into icecream (flavour) values ('Vanilla')
go
Run Code Online (Sandbox Code Playgroud)

运行这个,你会得到:

(1 row(s) affected)
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "ck_flavour". The conflict occurred in database "GAIUSDB", table "dbo.icecream", column 'flavour'.
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

这是一种高效、高性能的方法,但缺点当然是添加新风格意味着更改代码。我建议不要在应用程序中执行此操作 - 因为那样您需要在连接到此数据库的每个应用程序中执行此操作,这是最简洁的设计,因为只有一个代码路径用于进行验证。


Cod*_*awk 7

“直接使用查找值”——与查找表的实际目的有点矛盾。你为什么要保留这样一张桌子?如果不是查找。
可能是我误解了你的问题。这是来自msdn的查找表定义

查找表用于根据另一个表中的外键字段的值显示一个表中的信息。例如,考虑销售数据库中的订单表。Orders 表中的每条记录都包含一个 CustomerID,指示下订单的客户。CustomerID 是指向客户表中客户记录的外键。在显示订单列表(来自订单表)时,您可能希望显示实际客户名称,而不是 CustomerID。由于客户名称在客户表中,并且您正在显示订单表中的数据,因此您需要创建一个查找表,该表获取订单记录中的 CustomerID 值,并使用该值来导航关系并返回更多可读,客户名称。

你能详细说明你的查找表的目的吗?它是用来存储一些像下面这样的静态数据,这些记录不是其他表记录的输入吗?

风味

Orange  
Pista  
Mango
Run Code Online (Sandbox Code Playgroud)

如果以上是你的情况,那么我建议不要使用查找表;可能在您的 Web 应用程序中对这些列表值进行硬编码。这样可以避免不必要的数据库查询。


小智 7

由于您使用“专门针对查找表”来限定您的问题,因此答案可能会简化为“节省空间”。

我想如果你删除那个限定符,你的问题就变成了“为什么要使用代理键而不是自然键?” 我写了以下内容来支持代理键:

“迁移一个整数值而不是更广泛的复合键有很多好处。它在整个物理模型中提供了很好的一致性,与迁移复合键相比,总的来说,它节省了更多的空间而不是成本,并减少了 I/O;尤其是在一个井中——规范化模型。此外,它们简化了对模型和查询连接的理解。”

这在很大程度上就是为什么它“成为标准做法”的原因。不幸的副产品是人们扔了一个代理键而不去想候选键是什么......但现在我们已经超出了你的问题:)