引入
當我們在數據庫中創建表的時候,有可能某些列中值內容量很大,而且重復。
例子:創建一個學生表,按學校年紀班級分,表的內容大致如下:
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:
創建person:

create table person( nid int not null auto_increment, name varchar(32) default null, email varchar(32) default null, part_nid int, primary key(nid), constraint fk_person_part foreign key (part_nid) references part(nid) )
創建完之后外鍵對應代碼的關系:
分析:
1、從名字可以看出代碼對應的是什么位置的。
2、圖中名(C對應代碼中的CONSTRAINT)這行可以不用設,系統會默認幫我設置,但是最好設置,如果要刪除外鍵的時候,就可以通過這個名字進行相應的操作。
代碼刪除外鍵
alter table person1 drop foreign key fk_person1_part1;
代碼增加外鍵
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
select name from person where part_id in (select nid form part where caption = "x")
2、鏈表方法 left join
left join
使用連表提供的方法,left join操作代碼:
select * from person left join part on person.part_id = part.nid
結果顯示:
分析:
left join:相當於將part表匹配的部分直接移動到person的列后面,組合起來顯示。
既然內容都合並了,那么此時我們再加上判斷,就可以將要的數據獲取了。
代碼1:
select * from person left join part on person.part_id = part.nid where part.caption = "x"
結果:
說明:
之前我們用的
*
獲取的是全部的信息,如果我們獲取指定的信息,可以將其修改。如:只獲取person的name代碼:
select person.name from person left join part on person.part_id = part.nid where part.caption = "x"
結果:
注意:
join連接的條件,使用 on 進行對接的,條件寫在on后面。
A left join B on a.xx = b.xx
left join的特點:
1、以A為主
2、將A中的所有數據羅列
3、B則只顯示與A相對應的數據
問題:驗證我們說的誰在前就誰為主,誰的數據就全部顯示,我們將person和part換個位置?
select * from part left join person on person.part_id = part.nid;
結果:
right join
在誰顯示所有數據的上來看,他和left join剛好相反,以后面的表為主,顯示其所有的數據。
inner join
會將沒有建立關系的數據忽略掉。不管誰在前,結果都是一樣。
select * from person inner join part on person.part_id = part.nid;
結果:
總結:
1、這幾個join可以寫多個的,意思就是一個表可以同時有多個外鍵。2、當選擇的列名,是所有表中唯一的話,可以不用寫前綴的表名。如:person.part_id就可以直接寫成part_id.
3、上面的part表,有個別名叫,字典表