我可以使用 VARCHAR 作为主键吗?

我有一个用于存储优惠券/折扣的表,我想使用优惠券 _ code 列作为主键,它是一个 VARCHAR

我的基本原理是,每张优惠券都有一个唯一的代码,我将运行的唯一命令是 SELECT ... FROM ... WHERE coupon_code='..'

我不会进行任何连接或索引操作,我也不认为这个表中有超过几百个条目。

在我看来,这将是好的,但我不知道是否有什么我错过/没有思考。

140535 次浏览

当然可以,因为您的 RDBMS 允许您这样做。但是,对于 应该是否执行这个操作的问题,答案是不同的: 在大多数情况下,在数据库系统之外具有意义的值应该选择 没有作为主键。

如果您知道该值在所建模的系统中是唯一的,那么向表中添加唯一索引或唯一约束是合适的。但是,您的主键通常应该是一些“无意义”的值,例如自动递增的数字或 GUID。

这样做的原因很简单: 数据输入错误和对看起来不可更改的内容的频繁更改确实会发生。它们变得更加难以固定用作主键的值。

当然没问题,只要有几百个参赛者,就会很快。

您可以添加一个唯一的 id 作为主键(int auto 自動增量) ,然后将您的 couon _ code 設置为惟一的。因此,如果需要在其他表中执行 request,最好使用 int 而不是 varchar

“不,你不应该”是个糟糕的建议。这在很多情况下是完全合理的,具体取决于您的用例、工作负载、数据熵、硬件等等。不应该所做的就是做出假设。

值得注意的是,您可以指定一个前缀来限制 MySQL 的索引,从而在扫描其余内容之前帮助您缩小结果范围。然而,随着时间的推移,这可能会变得不那么有用,因为您的前缀“填充”,并变得不那么独特。

做起来很简单,例如:

CREATE TABLE IF NOT EXISTS `foo` (
`id` varchar(128),
PRIMARY KEY (`id`(4))
)

还要注意,前缀 (4)出现在列引号 之后中。其中,4意味着它应该使用可以作为 id存在的128个可能字符中的前4个字符。

最后,在使用索引前缀之前,您应该了解它们是如何工作的以及它们的局限性: https://dev.mysql.com/doc/refman/8.0/en/create-index.html

这取决于具体的用例。

如果您的表是静态的,并且只有一个很短的值列表(并且在 DB 的生存期内这种情况发生变化的可能性很小) ,我建议使用以下结构:

CREATE TABLE Foo
(
FooCode VARCHAR(16), -- short code or shortcut, but with some meaning.
Name NVARCHAR(128), -- full name of entity, can be used as fallback in case when your localization for some language doesn't exist
LocalizationCode AS ('Foo.' + FooCode) -- This could be a code for your localization table... 
)

当然,当您的表根本不是静态的时候,使用 内景作为主键是最好的解决方案。