我经常遇到这样的情况:
table `user_adress`
+----------+-------------+--------------+---------+
|adress_id | user_id | adress_type |adress |
+----------+-------------+--------------+---------+
| 1 | 1 | home |adressXXX|
| 2 | 2 | home |adressXXX|
| 3 | 3 | home |adressXXX|
| 4 | 1 | work |adressXXX|
| 5 | 2 | work |adressXXX|
| 6 | 1 | second_home |adressXXX|
+----------+-------------+--------------+---------+
如果我想使用它,我正在使用如下查询:
SELECT `adress` FROM `user_adress` WHERE `user_id`=1;
看起来很正常,但事实是,我使用了“无用的” adress_id
列,它没有其他用途,而是为了自动增加主键,只是为了在MySQL表中拥有主键。我从不使用或不需要此号码。因此,我发现我根本不应该在表中使用主键,而应完全删除adress_id
,并在INDEX
列中设置unique
(无user_id
)。看起来不错-还是我错了?
我有一些疑问,因为在我阅读的文章中,到处都有建议,每个表都应该甚至需要具有主键。但为什么?如果我允许这种情况发生,也许我的数据库设计不佳,但是看着我极其简单的示例表-我无法想象在每种情况下都可能出现这种情况,尤其是在这种简单情况下。我明确地误解了一些有关创建表并正确索引它们的简单基本规则-我的难题在哪里?
答案 0 :(得分:1)
从您的数据中可以明显看出,主键允许直接访问单行而没有任何问题或歧义..(尤其是删除或更新)
这是主键的专门用途。
事实上您可能需要通过user_id将此表与其他表连接
和user_id上的索引(不是唯一的)
create index myidx on mytable(user_id)
对于加快连接速度非常有用,它只允许在与单个user_id相关的行上直接访问
答案 1 :(得分:1)
完全基于您的表结构,我会说您的主键不正确。
相反,您的主要对象应该是:
PRIMARY KEY (user_id, address_type)
您是正确的,每个表在理想情况下都应具有主键,但是主键可以覆盖多个字段。
使用简单的自动递增ID作为主键有时仍然更容易。 Innodb存储引擎实际上将在不可见的字段中秘密地执行此操作。
也许在您的有限示例中,它不是必需的,但在许多实际情况下,它可以使处理数据更加容易。从这种意义上讲,我要说的是,从学术的角度来看,拥有人工自动递增的主键不是最佳实践,但是从“现实世界,操作和MySQL管理员”的角度来看,这可能是个好主意。
还有一些仅要求此的ORM系统(就那样不好)。
答案 2 :(得分:1)
关系数据库表确实需要一个主键。
但这全都归结为主键的定义。主键不一定是自动递增的单个整数列。
主键是可以唯一标识每一行的任何列或一组多列。在您的情况下,user_id
和address_type
的组合可以做到这一点(如Evert已发布)。
因此,如果您像这样制作表格:
CREATE TABLE user_address (
user_id INT NOT NULL,
address_type varchar(10) NOT NULL,
address TEXT NOT NULL,
PRIMARY KEY (user_id, address_type)
);
然后您可以一次更新或删除一个特定行:
UPDATE user_address SET ...
WHERE user_id = ? AND address_type = ?;
有些人认为,强制执行约定(每个表都应具有单个整数列作为其主键)更为方便。他们甚至可能坚持认为,为了保持一致性,必须将列命名为id
。
在一致性方面有一些优势,但是另一方面,即使没有帮助,坚持这种约定也有点不明智。