資料庫(三)
前言
本篇部落格主要內容為表之間的關係、多表關聯、複製表;查詢如單表查詢、多表關聯查詢
表之間關係
為什麼要分表?
假如現在有兩種資料,一種是部門資料一種是員工資料,如果兩中資料放在同一張表中則會造成:
- 資料重複
- 結構混亂
- 擴充套件維護性差
- 需要分表
所以需要把表中會造成混亂的資料分出來,分成兩張表。
mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),gender char,age int,salary float,d_id int);
什麼時候需要分表?
當出現大量重複資料時,當一條記錄中的資料不屬於同一類時需要分表。
分表之後產生的問題,員工表可以儲存一個不存在的部門編號,這樣的資料是不完整的無效資料,必須找到一種方法可以在物理層面建立關聯關係。
以上建表語句可以建立邏輯上的關聯關係,這有建表的人才明白其中的關係,而 mysql 並不知道關係,所以需要通過外來鍵來進行約束,說明這兩張表的關聯關係。
外來鍵的使用
mysql> create table 表名(欄位名 型別(長度),foreign key(外來鍵的欄位名) references 要關聯表名(主鍵名));
使用外來鍵時必須分清主從關係,也就是要分清先鍵那張表,因為在使用外來鍵關聯表時,需要知道對方表的表名,所以要關聯的表應該是主表,應該先建主表,這樣才能關聯起來。
外來鍵的第一個約束
先鍵主表,再建從表
mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id));
外來鍵的第二個約束
資料先插入主表,再插入從表資料
mysql> insert into dept values(1,'hr','招聘');
mysql> insert into emp values(1,'張無忌',1);
外來鍵的第三個約束
刪除資料時先刪從表,再刪主表
mysql> delete from emp where name = '張無忌';
mysql> delete from dept where id = 1;
外來鍵的第四個約束
從表更新外來鍵時必須保證外來鍵是存在的。
外來鍵的第五個約束
更新主表的 id 時,要麼先刪除從表關聯的資料,或者把關聯資料關聯到其他的主表 id。
有了這幾種約束後,可以保證資料的完整性。相應的受到外來鍵約束,主表的刪除和更新操作受到限制,很多情況下,刪除主表某個資料需要至少兩條sql 語句,會很麻煩。
外來鍵的第六個約束
刪除主表時,要先刪除從表。
級聯操作
刪除級聯
當主表刪除時,從表相關聯的記錄同步刪除
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id) on delete cascade);
更新級聯
當主表 id 時,從表相關聯的記錄通步更新
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id) on update cascade);
級聯方向只能是主表級聯從表,可以在操作主表時自動操作從表。(單箱操作,主表變化是級聯操作從表,從表的變化不會影響主表)
一對一關係
一對一的關係只需要加一個外來鍵來關聯即可,但是需要給外來鍵加上唯一約束。有主從關係的都需要先建主表。
mysql> create customer(c_id int primary key auto_increment,name char(20),phonenum char(11),addr char(20));
mysql> create student(s_id int primary key auto_increment,name char(20),class char(11),number char(20),housenum char(20),c_id int unique,foreign key(c_id) references customer(c_id));
一對一的另一種使用場景,當一個表的欄位太多,而常用的欄位不多時,可以採取垂直分表的方式來提高效率,比如個人資訊有身份證、性別、年齡、地址等,可以拆分為基礎資訊和細節資訊;也有另一種提升效率的方式,水平分表,當一個表中的資料記錄太多時,效率會降低,可以採取水平分表,欄位完全相同。
多對多關係
假如有兩張表,一張表存的是老師,另一張表存的是學生。因為一個老師可以教多個學生,一個學生也可以有多個老師,所以這是雙向多對一的關係,也就是多對多的關係。那麼應該怎麼儲存資料呢?
可以通過增加一箇中間表來儲存兩張表的關係,然後其他兩張表分別用一個欄位作為外來鍵來關聯中間表。(只要是多對多關係都是靠中間表來儲存兩張表之間的關係)除了中間表,另外兩張都是主表,具體先建哪種主表沒有先後順序。多對多關係至少需要三張表。
mysql> create table stu(id int primary key auto_increment,name char(20));
mysql> create table tea(id int primary key auto_increment,name char(20));
mysql> create table tsr(id int primary key auto_increment,t_id int,s_id int,foreign key(t_id) references tea(id),foreign key(s_id) references stu(id));
因為老師和學生都是主表,關係表是從表,所以需要先插入老師和學生的資料,接著插入中間表的資料。
多對多關係表中因為已經有了 id 為主鍵,所以可以重複存入相同的學生和老師關係資料,可以通過聯合主鍵改變。
多對一關係
mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id));
複製表
mysql> create table 新表名 select * from 被複制的表名;
注意不會複製主鍵和約束條件,資料結構都可以複製。
mysql> create table 新表名 select * from 源表名 where 1 = 2;
當where 後面條件不成立時,只會複製表結構。
蠕蟲複製
自我複製。
mysql> insert into 表名 select * from 表名;
如果有主鍵
mysql> insert into 表名(其他欄位) select 其他欄位 from 表名;
在日常開發中,如果對效能要求很高,不應該使用外來鍵
- 效率降低
- 耦合 關係多起來會造成管理麻煩
這時候關係只是邏輯關係很有可能產生錯誤資料。