在MySQL中如何设置主键和外键

记得有一次,我是一家公司数据库管理团队的成员,正忙着优化一个电商平台的订单管理系统。
前几天,我们遇到了一个难题:排序表中有些数据重复,导致查询效率低下。
我决定从设置主键开始。

我坐在电脑前,打开MySQL命令行工具,输入命令切换到目标数据库。
然后,我发现原来的表已经有了主键,但是它的设置不够合理。
您已输入 ALTER TABLE jingyan DROP PRIMARY KEY;命令执行成功,主键消失。

接下来,小心输入ALTER TABLE jingyan ADD PRIMARY KEY(id);。
屏幕上立即显示“Query OK, 0受影响行”字样,此时主键添加成功。
然后我切换到数据库可视化工具,果然ID列中多了一个主键标签。

这时我突然想到,我们可能需要设置一些外键来维护数据的完整性。
因此,我按照以下步骤创建关键详细信息表并设置外键。
看着这一切,我暗暗为自己在这么短的时间内解决了问题而感叹。

但是等等,还有别的事情。
刚刚设置的这些外键在实际应用中能起到维护数据完整性的作用吗?

mysql主键和唯一键区别?如何选择主键?

哈哈,你的总结很全面,直接复制数据库课的笔记就可以了。
但要说根本的区别,就得修改几个规则……上周我给实习生讲这件事的时候,我直接告诉他:
你看,上周有一个客户问我,为什么他的表用自增ID作为主键,然后加了一个唯一键来限制手机号码。
结果,选择很慢。
其实原因很简单。

主键是表中的ID号,必须全局唯一,不能为空。
为什么?因为你需要使用这个数字将其链接到其他表,例如排名表链接到用户表。
如果用户ID为空或重复,则数据链接将直接断开。
因此,主键最重要的是“唯一性”和“不变性”,不能被意外改变。
我以前曾陷入过一个陷阱,并使用电子邮件作为主键。
结果,用户更改了电子邮件,所有订单关联都变得无效。
我不得不连夜更改数据库。
因此,主键最好是一个永远不会改变的数字,比如INT AUTO_INCRMENT,这样简单、简单、有效。

唯一密钥与“购买限制代码”非常相似。
比如手机号码、用户名,这些字段必须是唯一的,但它们并不像主键那样神圣。
唯一键可以为空,因此它们之间的区别是“空”和“数字”。

一张表只能有一个主键,但可以有多个唯一键。
想一想,在orders表中,order_id是主键,但也可以将user_id+product_id设置为唯一键,防止一个人重复购买同一个订单。
就好像身份证号码是唯一的,但是你的手机号码和邮箱也可以设置成唯一的,但是身份证号码只有一个。

在索引区域中,主键默认会提供整个聚集索引。
数据直接按照主键排队,验证速度非常快。
唯一键是常规索引。
必须先找索引,然后再找数据,所以速度有点慢。
但唯一键也可以用作聚集索引,但一般不推荐使用,因为过于复杂。

总而言之,当您选择主键时,您会想到“唯一标识符”,而当您选择唯一键时,您会想到“防止我说了,自增ID最好,不要用UUID,太大了很乱,容易分裂索引。
不要用业务字段做主键,比如你改了ID号,相关的表都得改,简直就是噩梦。

反正你想怎么做就怎么做,这都是我的经验。

MySQL中处理唯一键冲突:使用错误码1062

呃...MySQL中的唯一键冲突...以我2 02 2 年在上海遇到的一个项目为例。
当时确实很困难。
我的数据表中有一个字段必须是唯一的。
结果,用户疯狂提交,结果很快就增长到了1 06 2 这段代码MySQL应该是专门为这种情况保留的。

当时我用的是PHP+mysqli。
我编写第一个代码的方式很奇怪。
您所要做的就是将用户输入的值输入到 SQL 语句中并将它们串在一起。
像这样:
php $sql = "INSERT INTO Order (order_id) VALUES('" . $user_input_id . "')"; $conn->查询($sql);
结果如何?如果用户输入重复的数字,数据库就会崩溃并报告大量乱码错误信息。
经过长时间的调试,我发现这是不可能的。
SQL注入的风险很高,如果用户输入的值恰好在SQL语句中包含特殊字符,整个查询就会挂起。
也很容易做出错误的决定。
有时错误消息不是重复的键,但它实际上看起来像重复的键,这令人困惑。

后来改为使用准备好的语句。
这是正确的方法。
像这样:
php $stmt = $conn->prepare("插入订单 (order_id) value(?)"); $stmt->bind_param("s", $user_input_id); $stmt->execute();
这样就安全多了。
数据和代码是分开的。
执行后还应该检查 errno。

PHP if ($stmt->errno == 1 06 2 ) { echo "已有人使用此订单号下单,请尝试其他号码。
"; 否则 if ($stmt->errno) { // 其他数据库错误,例如连接超时 error_log("数据库错误:" . $stmt->error); echo "系统出现错误,请稍后重试。
"; } 否则{ echo "订单成功完成!"; }
如果您看到 1 06 2 ,则表明用户输入的值在数据库中重复。
直接告诉用户不要乱搞,改成别的东西。
为了避免泄漏数据库结构信息,请记录其他错误,并且不要直接向用户显示它们。

现在,关键是prepared statements和errno判断。
2 02 2 年的项目采用了这个方法,之后没有出现大问题。
请注意,您必须使用准备好的语句。
另外,如果 errno 为 1 06 2 ,则它是重复键,无法猜测。