MYSQL外键

请注意 :
1、外键约束只能在innodb引擎下使用。
2、外键应该在建立子表的时候建立。
3、外键所建立的字段,其字段类型应该与父表中对应的字段类型相同。例如同为INT。若不同在建立外键时会报一个150的错误码。

下面我们先来创建一张主表

mysql> create table grades(
    -> id tinyint not null auto_increment primary key comment '自增主键',
    -> grade_name varchar(40) not null comment '年级名称'
    -> )engine=innodb default charset=utf8 comment '年级表';
Query OK, 0 rows affected (0.00 sec)

mysql> desc grades;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | tinyint(4)  | NO   | PRI | NULL    | auto_increment |
| grade_name | varchar(40) | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

可以看到我们已经成功创建了一张年级表,接下来我们再创建一张学生表,并且为学生表创建外键,关联年级表的id字段。

注意关键语法:constraint 外键名 foreign key(需要设置外键的字段) references 父表(父表关联的字段)

mysql> create table students (
    -> id int not null auto_increment primary key comment '自增id',
    -> name varchar(45) not null comment '学生姓名',
    -> g_id tinyint not null comment '年级ID 后面会设置外键约束',
    -> constraint fk_grade_id foreign key(g_id) references grades(`id`)
    -> )engine=innodb default charset=utf8 comment '设置了外键约束的学生表';
Query OK, 0 rows affected (0.01 sec)

设置外键联动

但是我们仅仅是建立了外键,并没有指定它的联动关系,所以这个外键实际上是并没有什么用处的。
外键的联动可以通过on deleteon update来触发。

触发的效果有三种:
1、cascade关联操作,如果主表被更新或删除,从表也会执行相应的操作
2、set null,表示从表数据不指向主表任何记录 即当主表数据更新后不存在时将从表的外键值设为空
3、restrict:拒绝主表的相关操作 即主表没有的数据 都不能添加或更新

设置外键的正确姿势应该是constraint 外键名 foreign key(需要设置外键的字段) references 父表(父表关联的字段) on delete/update cascade/restrict/set null ;

删除错误的外键

我们现在来删除一开始创建的并没有什么卵用的外键

mysql> alter table students
    -> drop foreign key 
    -> fk_grade_id;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

在已有的表上创建一个新的外键

mysql> alter table students  add constraint fk_id foreign key(g_id) references grades(`id`) on update restrict on delete cascade;

Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

注意:on delete 时不能设置动作为 set null 否则会报一个ERROR 1005 (HY000): Can’t create table ‘demo.#sql-1fcc_3’ (errno: 150)的错误

解释一下上面的sql:修改表students ,新增一个外键约束,外键约束的名称是
fk_id,关联的父表是grades关联键名是父表下的id设置约束为,更新操作如果父表没有值,则子表拒绝操作。删除动作,子表随父表而执行。

新的外键约束已经创建完成,我们来测试一下。
首先在父表没有数据的情况下向子表内插入一条记录:

mysql> insert into students(name,g_id) values('lisi',2);

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`demo`.`students`, CONSTRAINT `fk_id` FOREIGN KEY (`g_id`) REFERENCES `grades` (`id`) ON DELETE CASCADE)

可以看到报了一个错误,无法插入。接下来我们先在父表写入一条测试数据,然后再在子表插入。

mysql> insert into grades(grade_name) values('一年级');
Query OK, 1 row affected (0.00 sec)

mysql> select * from grades;
+----+------------+
| id | grade_name |
+----+------------+
|  1 | 一年级     |
+----+------------+
1 row in set (0.00 sec)

mysql> insert into students(name,g_id) values('lisi',1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from students;
+----+------+------+
| id | name | g_id |
+----+------+------+
|  2 | lisi |    1 |
+----+------+------+
1 row in set (0.00 sec)

可以看到 插入成功了。下面我们删除父表中的数据,然后看子表

mysql> delete from grades where id =1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from grades;
Empty set (0.00 sec)

mysql> select * from students;
Empty set (0.00 sec)

可见,删除联动也没有问题。

### MySQL的使用方法与问题排查 在MySQL中,(Foreign Key)用于维护之间的参照完整性。约束要求子中的值必须出现在父的主或唯一值中。如果违反了这种约束,数据库操作将被阻止。 当创建时,必须确保父和子都满足以下条件[^1]: - 父必须包含一个索引(通常是主或唯一索引),该索引对应于子的列。 - 子中的列也必须有索引支持,否则会抛出错误“Failed to add the foreign key constaint. Missing index for constraint”。 以下是创建的基本语法: ```sql ALTER TABLE child_table ADD CONSTRAINT fk_name FOREIGN KEY (child_column) REFERENCES parent_table(parent_column) ON DELETE CASCADE ON UPDATE CASCADE; ``` 此,如果启用了`sql_require_primary_key`系统变量,则尝试删除主会导致错误[^2]。这意味着,在设计数据库结构时,需要特别注意主的存在性以及其对其他依赖关系的影响。 对于问题的排查,可以按照以下方法进行: 1. 检查父是否为主或唯一添加了索引。 2. 确保子列已建立索引。 3. 验证数据类型和字符集的一致性。父和子的相关列必须具有相同的数据类型和字符集设置。 如果遇到具体错误,例如“Missing index for constraint”,可以通过以下SQL语句检查现有索引: ```sql SHOW INDEX FROM child_table; ``` 这有助于确认列是否确实存在索引。 #### 示例:修复约束问题 假设存在如下两张: - `parent_table(id INT PRIMARY KEY)` - `child_table(child_id INT, parent_id INT)` 若要为`child_table`添加约束,但出现错误,可以先为`parent_id`添加索引: ```sql ALTER TABLE child_table ADD INDEX (parent_id); ALTER TABLE child_table ADD CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent_table(id); ``` ### 关于phpMyAdmin测试环境 在实际部署过程中,如果因版本过低无法完成某些功能测试,可以考虑使用phpMyAdmin作为替代工具[^3]。通过图形化界面,用户能够更直观地管理数据库对象,包括创建、修改和删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值