必须严格按规则设置主键与外键:主键需not null+自增、类型匹配业务规模、复合主键慎用;外键要求引擎统一为innodb、字段类型与字符集一致、父表被引用列有索引;on delete cascade需防缓存不一致,set null需字段允许null,on update cascade极慎用。

要在数据库设计中避免插入失败、级联误删、索引失效和建表报错,必须严格按规则设置主键与外键,而不是照着语法写完就以为万事大吉。
主键怎么设才真正生效
第一步:创建表时直接声明主键并强制非空+自增,例如:id INT NOT NULL AUTO_INCREMENT PRIMARY KEY。漏掉 NOT NULL 会导致后续插入不带 id 值的记录时直接报错。
第二步:主键字段类型要匹配业务规模。用户量预估超千万,别用 SMALLINT;若用字符串作主键(如身份证号),必须加 NOT NULL 且长度精确(VARCHAR(18)),否则索引膨胀、JOIN 变慢。
第三步:复合主键仅在逻辑上必须联合唯一时才启用,比如 (order_id, line_no) 表示订单明细行序号。但要注意——MySQL 不会为该组合自动创建覆盖索引,查询时若只用 order_id,性能可能不如单列主键。
外键声明前必须确认的三件事
方法一:检查引擎是否统一。父表和子表都必须是 InnoDB,MyISAM 表里写 FOREIGN KEY 语法完全被忽略,不报错也不生效。
方法二:核对数据类型与字符集。父表是 INT UNSIGNED,子表外键字段就不能是 INT SIGNED;若父表字符集为 utf8mb4_unicode_ci,子表对应字段也必须一致,否则建表卡在 ERROR 1215。
方法三:确保被引用字段已有索引。外键列本身不要求索引,但父表被引用列(如 users.id)必须是主键或已单独建索引。没索引的话,外键约束无法建立,且后续 SELECT ... JOIN 会全表扫描。
ON DELETE 和 ON UPDATE 的实操选择
ON DELETE CASCADE 适合强生命周期绑定场景,比如删除商品时连带清空其历史价格记录。但注意:应用层若缓存了该商品 ID,数据库删完后缓存未失效,就会返回“商品存在但查不到详情”的脏状态。
ON DELETE SET NULL 要求子表字段允许为 NULL,否则建表失败;如果该字段上有 NOT NULL 约束或业务逻辑禁止为空(如订单必须归属有效用户),这个选项根本不可用。
ON UPDATE CASCADE 很少用——主键值本不该被更新。一旦开启,修改父表主键会批量触发子表更新,极易锁表卡住写入。除非你明确接受这种风险,否则默认不写这一项更安全。











