MySQL数据库——外键约束


把用户信息及其收货地址保存在数据中

方案一:单张表

创建表

create table user_info(
  id char(36) primary key,
  user_name varchar(30) not null,
  password varchar(30) not null,
  real_name varchar(8),
  mobile char(11),
  address varchar(150)
);

表中的id使用由java工具类生成的UUID保证id的唯一性
插入数据

insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('1e8e8d94-61b3-40b3-8e80-4890119d7c74','appache','123456','Lucy','18920120206','USA');

insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('e6952417-96f9-4f61-8f8e-a67ff6b4bb69','appache','123456','Tom','18617297545','UE');

insert into user_info (id,user_name,password,real_name,mobile,address)
values ('e4d4aaf2-6412-41ad-9157-acec294f0b36','appache','123456','Tim','17694976949','Japan');

插入数据后的user_infor表
由于每个用户可以有多个收货地址,可以看出这种方法创建的表存在较为严重的字段冗余(user_name和password列),而随着该表中的个人信息字段越来越多,则这一问题表现的就越严重,所以不推荐使用。为了解决字段冗余的问题我们可以创建两张表,一张用来保存个人信息,另外一张用来保存收货地址。

方案二:两张表

创建表user_info

create table user_info(
  id char(36) primary key,
  user_name varchar(30) unique not null,
  password varchar(30) not null
)

插入数据

insert into user_info (id,user_name,password) values ('1e8e8d94-61b3-40b3-8e80-4890119d7c74','appache','123456');

第一张表插入数据
创建表address

create table address(
  id char(36) primary key,
  user_info_id char(36),
  real_name varchar(8) not null,
  mobile char(11) not null,
  address varchar(150) not null
)

user_info_id对应 user_info表中的id字段
插入数据

insert into address (id,user_info_id,real_name,mobile,address) 
values ('bfb9472a-7911-4e6f-a479-3b719454ebab','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Lucy','18920120206','USA');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Tom','18617297545','UE');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Tim','17694976949','Japan');

向第二张表中插入数据
这种方法虽然解决了字段的冗余问题,但由于只是逻辑上的“外键”关系,在插入数据的时候需要靠数据库操作者的自觉性,所以依然无法保证数据完整性,有可能会出现垃圾信息(没有用的信息)存在
如果这里在向aadress表中添加一条数据并且该数据没有与之对应的用户信息则这里添加的数据就是没有用的信息

insert into address (id,user_info_id,real_name,mobile,address) values ('7da42cc6-36a6-4ad5-9998-71dbc30c8e17','ddc376dd-f8b3-42a6-b42a-db22abed1941','xiaowang','18338970095','China');

向address表中插入数据
如果这里如果把user_info表中的数据删除但此时地址表中数据将不再完整,这些地址没有与之对应的用户。此时addres表中与之前用户对应的收货地址成为了垃圾信息。
把user_info中的数据删除
address表中的数据依然存在
这里只是逻辑上的“外键”关系,所以还需要手动删除address表中对应的数据。

显然逻辑上的"外键"关系需要依靠操作者的自觉性,依然无法保证数据的完整性。

方案三:两张表并添加外键约束

创建表user_info

create table user_info(
  id char(36) primary key,
  user_name varchar(30) not null,
  password varchar(30) not null
)

插入一条数据

insert into user_info (id,user_name,password) values ('1e8e8d94-61b3-40b3-8e80-4890119d7c74','appache','123456');

创建表address的同时添加外键约束

create table address(
  id char(36) primary key,
  user_info_id char(36),
  real_name varchar(8) not null,
  mobile char(11) not null,
  address varchar(150) not null,
  #下面这条语句就是在user_info_id添加了外键,指向user_info表的主键
  foreign key(user_info_id) references user_info(id)
)

插入数据

insert into address (id,user_info_id,real_name,mobile,address) 
values ('bfb9472a-7911-4e6f-a479-3b719454ebab','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Lucy','18920120206','USA');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Tom','18617297545','UE');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','1e8e8d94-61b3-40b3-8e80-4890119d7c74','Tim','17694976949','Japan');

这种方案为user_info_id添加了外键,指向user_info表的主键,该约束起到了保护数据完整性的作用:如果删除的用户信息id已经在address表中使用,则该条数据无法删除;无法向address表中添加用户id不存在的地址信息。
如果向address表中插入无关的信息

insert into address (id,user_info_id,real_name,mobile,address) values ('7da42cc6-36a6-4ad5-9998-71dbc30c8e17','ddc376dd-f8b3-42a6-b42a-db22abed1941','xiaowang','18338970095','China');

这里会报错

insert into address (id,user_info_id,real_name,mobile,address) values ('7da42cc6-36a6-4ad5-9998-71dbc30c8e17','ddc376dd-f8b3-42a6-b42a-db22abed1941','xiaowang','18338970095','China')
> 1452 - Cannot add or update a child row: a foreign key constraint fails (`user_info`.`address`, CONSTRAINT `address_ibfk_1` FOREIGN KEY (`user_info_id`) REFERENCES `user_info` (`id`))
> 时间: 0.009s

如果这里删除表user_info,也会报错

#以下两条语句中的任意一条即可
delete from user_info
delete from user_info where id = '1e8e8d94-61b3-40b3-8e80-4890119d7c74';

这里也会报错

delete from user_info
> 1451 - Cannot delete or update a parent row: a foreign key constraint fails (`user_info`.`address`, CONSTRAINT `address_ibfk_1` FOREIGN KEY (`user_info_id`) REFERENCES `user_info` (`id`))
> 时间: 0.019s

如果想要向address表中插入数据必须要和user_info_id指向的user_info表中的id相对应,否则无法插入
如果想要删除user_info表中的数据,必须把指向他的主键对应的数据先全部删除,否则无法删除

所以这种方案起到了保护数据完整性的作用,推荐使用该方案。


删除user_info表中的id=1e8e8d94-61b3-40b3-8e80-4890119d7c74数据

  1. 先把address表中user_info_id指向该id的数据删除
delete from address where user_info_id = '1e8e8d94-61b3-40b3-8e80-4890119d7c74';

结果如下
删除后的address表
2. 这时就可以删除user_info表中的数据

delete from user_infor where id = '1e8e8d94-61b3-40b3-8e80-4890119d7c74';

user_infor表中的数据删除成功

猜你喜欢

转载自blog.csdn.net/qq_35302939/article/details/89885874