74

我有一个用于存储优惠券/折扣的表,我想使用 coupon_code 列作为主键,即VARCHAR.

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

我不会做任何连接或索引,而且我看不到这个表中有超过几百个条目。

在我看来,这会没问题,但我不知道是否有什么我遗漏/没有考虑的事情。

4

4 回答 4

133

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

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

这样做的理由很简单:数据输入错误和对看似不可更改的事物的不频繁更改确实会发生。它们变得更难修复用作主键的值。

于 2013-10-10T15:26:52.137 回答
20

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

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

这很简单,例如:

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

另请注意,前缀(4)出现列引号之后。这4意味着它应该使用可以作为id.

最后,您应该在使用它们之前阅读索引前缀的工作原理及其限制:https ://dev.mysql.com/doc/refman/8.0/en/create-index.html

于 2014-04-06T14:41:06.903 回答
2

这取决于具体的用例。

如果您的表是静态的并且只有一个简短的值列表(并且在 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... 
)

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

于 2015-05-05T06:47:12.890 回答
-1

肯定没问题。只有几百个条目,它会很快。

您可以添加一个唯一 id 作为主键(int autoincrement),并将您的 coupon_code 设置为唯一。因此,如果您需要在其他表中进行请求,最好使用 int 而不是 varchar

于 2013-10-10T15:27:49.237 回答