例如:如何將一個用戶的用戶信息及其多個郵寄商品地址保存到數據庫中?(數據特點:有較多的冗餘數據,即賬戶和密碼相同其他信息有差別)
方案一:
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不存在的地址信息。