Mysql多表操作\\一對多
當我們在資料庫中建立表的時候,有可能某些列中值內容量很大,而且重複。
例子:建立一個學生表,按學校年紀班級分,表的內容大致如下:
id | name | partment |
1 | xxx | x學校x年級x班級 |
2 | ooo | x學校x年級x班級 |
3 | zzz | z學校x年級x班級 |
4 | ddd | y學校x年級x班級 |
我們看出來對應的partment對應的值很長,而且重複量很大,這樣就很不合適。
因此我們考慮將複雜重複的部分單獨拿出來分成2個表:
第一張表:
id | caption |
1 | x學校x年級x班級 |
2 | y學校x年級x班級 |
3 | z學校x年級x班級 |
第二張表在之前的基礎上修改的:
id | name | partment |
1 | xxx | 1 |
2 | ooo | 2 |
3 | zzz | 3 |
4 | ddd | 1 |
這樣看起來就很簡潔了,我們將很長的且重複的部分拿出來,然後規定編號,建立學生表的時候,學生對應的partment只需要取學校對應的id便可,這樣同時這2張表也就會關聯起來。
說明:
1、他們的關聯關係;表2中的partment和表1的id聯絡再一起。
2、表一的資料會對應表2中的多條資料,這就叫一對多。
問題:此時,兩張表是相對獨立的,都可以各自插入自己的資料,這樣做很合適的,並沒實質行的關聯?
因此,必須要將其限制。表二的partment資料必須是表一中有的,不然,就不讓其增加。
這裡(partment)就引入了一個名詞 —- 外來鍵
外來鍵
說明:
1、外來鍵:一個表接收另一個表的主鍵。
2、partment外來鍵的是表一中的nid。
3、當我們建立了外來鍵,則系統變預設會為我們新增,相應的約束,如:表二中的partment資料必須是表一中nid有的;表二和表一就關聯起來了。
Navicat建立外來鍵
建立part表:
建立person表:
外來鍵的建立注意點:
建立外來鍵時,互相對應的表中的資料型別必須一樣
。
建立外來鍵
1、首先在要建立外來鍵的表上右鍵,選設計表。
2、進入設計表,在右邊顯示錶行資訊,然後點選外來鍵:
3、選擇欄位,會出現一個選擇框,選擇你要設定外來鍵的列;
4、選擇參考表,選擇要外來鍵要關聯的表,
說明:
引數資料庫:因為兩個資料庫在同意目錄下,所以這裡可以不用選擇;預設是同目錄下的。
5、選擇參考欄位;選擇參考表中要設為外來鍵的列;
注意:
外來鍵的建立,連個表中關聯的列的資料型別必須一樣,不然不能成功。
6、儲存CTRL + S
使用外來鍵
此時part中沒有資料,如果此時你在person中新增資料,結果:
在part中新增資料,結果:
此時再在,person中新增資料:
注意:
這裡不能輸入part中nid沒有的值,不然也會報錯。
SQL命令建立外來鍵
建立part:
part建立person:
person建立完之後外來鍵對應程式碼的關係:
分析:
1、從名字可以看出程式碼對應的是什麼位置的。
2、圖中名(C對應程式碼中的CONSTRAINT)這行可以不用設,系統會預設幫我設定,但是最好設定,如果要刪除外來鍵的時候,就可以通過這個名字進行相應的操作。
程式碼刪除外來鍵
01 |
alter table person1 drop foreign key fk_person1_part1;
|
程式碼增加外來鍵
01 |
alter table person1 add constraint fk_p1_t1 foreign key (part1_nid) references part1(nid);
|
通過外來鍵進行資料操作
part表:
person表:
需求:要找出person表中屬於x學校的人?
1、之前學的辦法:
- 1、先去part中獲取x對應的nid
- 2、然後再通過這個nid與parson中part_id對用的關係,查找出對應的name
01 |
select name from person where part_id in ( select nid form part where caption = "x" )
|
2、連結串列方法 left join
left join
使用連表提供的方法,left join操作程式碼:
01 |
select * from person left join part on person.part_id = part.nid
|
結果顯示:
分析:
left join:相當於將part表匹配的部分直接移動到person的列後面,組合起來顯示。
既然內容都合併了,那麼此時我們再加上判斷,就可以將要的資料獲取了。
程式碼1:
01 |
select * from person left join part on person.part_id = part.nid where part.caption = "x"
|
結果:
說明:
之前我們用的
*
獲取的是全部的資訊,如果我們獲取指定的資訊,可以將其修改。如:只獲取person的name程式碼:
01 select
person.
name
from
person
left
join
part
on
person.part_id = part.nid
where
part.caption =
"x"
結果:
注意:
join連線的條件,使用 on 進行對接的,條件寫在on後面。
01 |
A left join B on a.xx = b.xx
|
left join的特點:
1、以A為主
2、將A中的所有資料羅列
3、B則只顯示與A相對應的資料
問題:驗證我們說的誰在前就誰為主,誰的資料就全部顯示,我們將person和part換個位置?
01 |
select * from part left join person on person.part_id = part.nid;
|
結果:
right join
在誰顯示所有資料的上來看,他和left join剛好相反,以後面的表為主,顯示其所有的資料。
inner join
會將沒有建立關係的資料忽略掉。不管誰在前,結果都是一樣。
01 |
select * from person inner join part on person.part_id = part.nid;
|
結果: