天天看點

什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?

首先我們先思考一個問題:

如何将京東"fuliuqingfeng"的使用者資訊及其多個郵寄商品位址儲存到資料庫中?

我們第一步會這樣操作實作:

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)
);
insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','fuliuqingfeng','123456','張三','18920120206','河南安陽');
insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('cc95772b-75a2-4702-bd99-4c3b0322d606','fuliuqingfeng','123456','李四','18617297545','北京海澱');
insert into user_info (id,user_name,password,real_name,mobile,address)
values ('c63028fd-cf8d-4dac-a278-b5cc8fd61e3c','fuliuqingfeng','123456','王五','17694976949','山西大同');
           

這樣在表中的形式為:

什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?

表中資料可以了解為:

 使用者名為fuliuqingfeng 支付密碼為 123456  但其有不同的收獲位址

如: 張三 聯系電話為18920120206 收獲位址為 河南安陽 下面也是這樣。

但我們可以看到這時表中的資料存在一個問題:

這種表結構存在嚴重的字段備援(user_name和password列),如果個人資訊字段比較多這一問題表現的越嚴重(比如再加入身份證資訊,這一列又會重複出現)。

是以我們可以做出改變,利用兩個表解決這樣的問題:

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 ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','fuliuqingfeng','123456');

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
)
insert into address (id,user_info_id,real_name,mobile,address) 
values ('bfb9472a-7911-4e6f-a479-3b719454ebab','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','張三','18920120206','河南安陽');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','李四','18617297545','北京海澱');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','王五','17694976949','山西大同');
           

結果為:

什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?
什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?

這種表結構消除了字段備援,但由于隻是邏輯上的“外鍵”關系,是以依然無法保證資料完整性

此時依然存在問題:

例如可以将user_info中id為51b28fe1-4ebf-41ac-a17b-d5e276861fd0的資料删除,但此時位址表中資料将不再完整——找不到這些位址屬于哪個使用者;再例如也可以向address表中添加一條user_info_id不存在的位址資訊(如:insert into address (id,user_info_id,real_name,mobile,address) values ('7da42cc6-36a6-4ad5-9998-71dbc30c8e17','ddc376dd-f8b3-42a6-b42a-db22abed1941','xiaowang','18338970095','北京東城區');)——同樣,該條資料并不完整,依然找不到這些位址屬于哪個使用者。

進而我們繼續改進:

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 ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','fuliuqingfeng','123456');

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,
  constraint address_user_info_id_fk 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','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','張三','18920120206','河南安陽');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','李四','18617297545','北京海澱');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','王五','17694976949','山西大同');
           

address表中添加一條user_info_id不存在的位址資訊時:

什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?

将user_info中id為51b28fe1-4ebf-41ac-a17b-d5e276861fd0的資料删除時:

什麼是外鍵? 為什麼需要外鍵?怎麼使用外鍵?

我們發現會報錯。

此時也就實作了我們所說的 "外鍵"。