爲什麼需要外鍵

例如:如何將一個用戶的用戶信息及其多個郵寄商品地址保存到數據庫中?(數據特點:有較多的冗餘數據,即賬戶和密碼相同其他信息有差別)

方案一:

create table user_info(#創建共享信息表格
  id char(36) primary key,#id信息爲主鍵
  user_name varchar(30) not null,#user_name不能爲空
  password varchar(30) not null,#password不能爲空
  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','山西大同');

MySQL數據庫運行結果:

問題:這種表結構存在嚴重的字段冗餘(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','北京東城區');)——同樣,該條數據並不完整,依然找不到這些地址屬於哪個用戶。

方案三:使用外鍵,這種情況下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 ('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','山西大同');

 說明:這種方案爲user_info_id添加了外鍵,指向user_info表的主鍵,該約束起到了保護數據完整性的作用:如果刪除的用戶信息id已經在address表中使用,則該條數據無法刪除;無法向address表中添加用戶id不存在的地址信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章