MySQL聯(lián)結(jié)表介紹以及使用詳解
MySQL的前情介紹
??大家好呀,今天是我第N次寫MySQL,也是最近才學(xué)習(xí)MySQL,也想著記錄一下自己的學(xué)習(xí)過程,并且分享給大家尼!
本章詳情
??本章將介紹什么是聯(lián)結(jié),為什么要使用聯(lián)結(jié),如何編寫使用聯(lián)結(jié)的SELECT語句。
聯(lián)結(jié)
前言
SQL最強(qiáng)大的功能之一就是能在數(shù)據(jù)檢索查詢的執(zhí)行中聯(lián)結(jié) (join)表。聯(lián)結(jié)是利用SQL的SELECT能執(zhí)行的最重要的操作,很好地理解聯(lián)結(jié)及其語法是學(xué)習(xí)SQL的一個(gè)極為重要的組成部分。
在能夠有效地使用聯(lián)結(jié)前,必須了解關(guān)系表以及關(guān)系數(shù)據(jù)庫設(shè)計(jì)的些基礎(chǔ)知識(shí)。下面的介紹并不是這個(gè)內(nèi)容的全部知識(shí),但作為入門已經(jīng)足夠了。
關(guān)系表
??理解關(guān)系表的最好方法是來看一個(gè)現(xiàn)實(shí)世界中的例子:
現(xiàn)在,假如有由同一供應(yīng)商生產(chǎn)的多種物品,那么在何處存儲(chǔ)供應(yīng)商信息(如,供應(yīng)商名、地址、聯(lián)系方法等)呢?將這些數(shù)據(jù)與產(chǎn)品信息分開存儲(chǔ)的理由如下。
- 因?yàn)橥还?yīng)商生產(chǎn)的每個(gè)產(chǎn)品的供應(yīng)商信息都是相同的,對(duì)每個(gè)產(chǎn)品重復(fù)此信息既浪費(fèi)時(shí)間又浪費(fèi)存儲(chǔ)空間。
- 如果供應(yīng)商信息改變(例如,供應(yīng)商搬家或電話號(hào)碼變動(dòng)),只需改動(dòng)一次即可。
- 如果有重復(fù)數(shù)據(jù)(即每種產(chǎn)品都存儲(chǔ)供應(yīng)商信息),很難保證每次輸入該數(shù)據(jù)的方式都相同。不一致的數(shù)據(jù)在報(bào)表中很難利用。
關(guān)鍵
關(guān)鍵是,相同數(shù)據(jù)出現(xiàn)多次決不是一件好事,此因素是關(guān)系數(shù)據(jù)庫設(shè)計(jì)的基礎(chǔ)。關(guān)系表的設(shè)計(jì)就是要保證把信息分解成多個(gè)表,一類數(shù)據(jù)一個(gè)表。各表通過某些常用的值(即關(guān)系設(shè)計(jì)中的關(guān)系 (relational))互相關(guān)聯(lián)。
分析
??在這個(gè)例子中,可建立兩個(gè)表,一個(gè)存儲(chǔ)供應(yīng)商信息,另一個(gè)存儲(chǔ)產(chǎn)品信息。vendors表包含所有供應(yīng)商信息,每個(gè)供應(yīng)商占一行,每個(gè)供應(yīng)商具有唯一的標(biāo)識(shí)。此識(shí)稱為主鍵 (primary key) (在第首篇文章中首次提到),可以是供應(yīng)商ID或任何其他唯一值。
products表只存儲(chǔ)產(chǎn)品信息,它除了存儲(chǔ)供應(yīng)商ID (vendors表的主鍵)外不存儲(chǔ)其他供應(yīng)商信息。vendors表的主鍵又叫作products的外鍵,它將vendors表與products表關(guān)聯(lián),利用供應(yīng)商ID能從vendors表中找出相應(yīng)供應(yīng)商的詳細(xì)信息。
外鍵(foreign key)
外鍵為某個(gè)表中的一列,它包含另一個(gè)表的主鍵值,定義了兩個(gè)表之間的關(guān)系。
好處
- 供應(yīng)商信息不重復(fù),從而不浪費(fèi)時(shí)間和空間;
- 如果供應(yīng)商信息變動(dòng),可以只更新vendors表中的單個(gè)記錄,相關(guān)表中的數(shù)據(jù)不用改動(dòng);
- 由于數(shù)據(jù)無重復(fù),顯然數(shù)據(jù)是一致的,這使得處理數(shù)據(jù)更簡單。
??總之,關(guān)系數(shù)據(jù)可以有效地存儲(chǔ)和方便地處理。因此,關(guān)系數(shù)據(jù)庫的可伸縮性遠(yuǎn)比非關(guān)系數(shù)據(jù)庫要好。
可伸縮性(scale)
能夠適應(yīng)不斷增加的工作量而不失敗。設(shè)計(jì)良好的數(shù)據(jù)庫或應(yīng)用程序稱之為可伸縮性好 (scale well)
為什么要使用聯(lián)結(jié)
正如所述,分解數(shù)據(jù)為多個(gè)表能更有效地存儲(chǔ),更方便地處理,并且具有更大的可伸縮性。但這些好處是有代價(jià)的。
??如果數(shù)據(jù)存儲(chǔ)在多個(gè)表中,怎樣用單條SELECT語句檢索出數(shù)據(jù)?
答案是使用聯(lián)結(jié)。簡單地說,聯(lián)結(jié)是一種機(jī)制,用來在一條SELECT語句中關(guān)聯(lián)表,因此稱之為聯(lián)結(jié)。使用特殊的語法,可以聯(lián)結(jié)多個(gè)表返回一組輸出,聯(lián)結(jié)在運(yùn)行時(shí)關(guān)聯(lián)表中正確的行。
維護(hù)引用完整性
維護(hù)引用完整性重要 的是,要理解聯(lián)結(jié)不是物理實(shí)體。換句話說,它在實(shí)際的數(shù)據(jù)庫表中不存在。聯(lián)結(jié)由MySQL根據(jù)需要建立,它存在于查詢的執(zhí)行當(dāng)中。
在使用關(guān)系表時(shí),僅在關(guān)系列中插入合法的數(shù)據(jù)非常重要?;氐竭@里的例子,如果在products表中插入擁有非法供應(yīng)商ID即沒有在vendors表中出現(xiàn))的供應(yīng)商生產(chǎn)的產(chǎn)品,則這些產(chǎn)品是不可訪問的,因?yàn)樗鼈儧]有關(guān)聯(lián)到某個(gè)供應(yīng)商。為防止這種情況發(fā)生,可指示MySQL只允許在products表的供應(yīng)商ID列中出現(xiàn)合法值(即出現(xiàn)在vendors表中的供應(yīng)商)這就是維護(hù)引用完整性,它是通過在表的定義中指定主鍵和外鍵來實(shí)現(xiàn)的。(這將在后面的文章種介紹)。
創(chuàng)建聯(lián)結(jié)
聯(lián)結(jié)的創(chuàng)建非常簡單,規(guī)定要聯(lián)結(jié)的所有表以及它們?nèi)绾侮P(guān)聯(lián)即可。請(qǐng)看下面的例子:
輸入
SELECT vend_name,prod_name,prod_price FROM vendors,products WHERE vendors.vend_id = products.vend_id ORDER BY vend_name,prod_name;
輸出

分析
我們來考察一下此代碼。SELECT語與前面所有語一樣指定要檢索的列。這里,最大的差別是所指定的兩個(gè)列(prod_name和prod_price)在一個(gè)表中,而另一個(gè)列(vend_name)在另一個(gè)表中。
現(xiàn)在來看FROM子句。與以前的SELECT語句不一樣,這條語句的FROM子句列出了兩個(gè)表,分別是vendors和products。它們就是這條SELECT語句聯(lián)結(jié)的兩個(gè)表的名字。這兩個(gè)表用WHERE子句正確聯(lián)結(jié),WHERE子句指示MySQL匹配vendors表中的vend_id和products表中的vend_id。
可以看到要匹配的兩個(gè)列以vendors.vend id和products.vend_id指定。這里需要這種完全限定列名,因?yàn)槿绻唤o出vend_id則MySQL不知道指的是哪一個(gè) (它們有兩個(gè),每個(gè)表中一個(gè))。
完全限定列名
在引用的列可能出現(xiàn)二義性時(shí),必須使用完全限定列名(用一個(gè)點(diǎn)分隔的表名和列名)。如果引用一個(gè)沒有用表名限制的具有二義性的列名,MySOL將返回錯(cuò)誤。
WHERE子句的重要性
提示
利用WHERE子句建立聯(lián)結(jié)關(guān)系似乎有點(diǎn)奇怪,但實(shí)際上,有一個(gè)很充分的理由。請(qǐng)記住,在一條SELECT語句中聯(lián)結(jié)幾個(gè)表時(shí),相應(yīng)的關(guān)系是在運(yùn)行中構(gòu)造的。在數(shù)據(jù)庫表的定義中不存在能指示MySQL如何對(duì)表進(jìn)行聯(lián)結(jié)的東西。你必須自已做這件事情。在聯(lián)結(jié)兩個(gè)表時(shí),你實(shí)際上做的是將第一個(gè)表中的每一行與第二個(gè)表中的每一行配對(duì)。WHERE子句作為過濾條件,它只包含那些匹配給定條件(這里是聯(lián)結(jié)條件)的行。沒有WHERE子句,第一個(gè)表中的每個(gè)行將與第二個(gè)表中的每個(gè)行配對(duì),而不管它們邏輯上是否可以配在一起。
笛卡爾積(cartesian product)
由沒有聯(lián)結(jié)條件的表關(guān)系返回的結(jié)果為笛卡兒積。檢索出的行的數(shù)目將是第一個(gè)表中的行數(shù)乘以第二個(gè)表中的行數(shù)。
為了理解這一點(diǎn),請(qǐng)看下面的SELECT語句及其輸出
輸入
SELECT vend_name,prod_name,prod_price FROM vendors,products ORDER BY vend_name,prod_name;
輸出

分析
從上面的輸出中可以看到,相應(yīng)的笛卡兒積不是我們所想要的。這里返回的數(shù)據(jù)用每個(gè)供應(yīng)商匹配了每個(gè)產(chǎn)品,它包括了供應(yīng)商不正確的產(chǎn)品。實(shí)際上有的供應(yīng)商根本就沒有產(chǎn)品。
不要忘記WHERE子句
應(yīng)該保證所有聯(lián)結(jié)都有WHERE子,否則MySQL將返回比想要的數(shù)據(jù)多得多的數(shù)據(jù)。同理,應(yīng)該保證WHERE子句的正確性。不正確的過濾條件將導(dǎo)致MySQL返回不正確的數(shù)據(jù).
叉聯(lián)結(jié)
有時(shí)我們會(huì)聽到返回稱為叉聯(lián)結(jié)(cross join)的笛卡兒積的聯(lián)結(jié)類型。
內(nèi)部聯(lián)結(jié)
目前為止所用的聯(lián)結(jié)稱為等值聯(lián)結(jié) (equijoin),它基于兩個(gè)表之間的相等測試。這種聯(lián)結(jié)也稱為內(nèi)部聯(lián)結(jié)。其實(shí),對(duì)于這種聯(lián)結(jié)可以使用稍微不同的語法來明確指定聯(lián)結(jié)的類型。下面的SELECT語句返回與前面例子完全相同的數(shù)據(jù):
輸入
SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products ON vendors.vend_id = products.vend_id;
分析
??此語句中的SELECT與前面的SELECT語句相同,但FROM子句不同。這里,兩個(gè)表之間的關(guān)系是FROM子句的組成部分,以INNER JOIN指定。在使用這種語法時(shí),聯(lián)結(jié)條件用特定的ON子句而不是WHERE子句給出。傳遞給ON的實(shí)際條件與傳遞給WHERE的相同。
使用哪種語法
ANSI SQL規(guī)范首選INNER JOIN語法。此外盡管使用WHERE子句定義聯(lián)結(jié)的確比較簡單,但是使用明確的聯(lián)結(jié)語法能夠確保不會(huì)忘記聯(lián)結(jié)條件,有時(shí)候這樣做也能影響性能。
聯(lián)結(jié)多個(gè)表
?SQL對(duì)一條SELECT語句中可以聯(lián)結(jié)的表的數(shù)目沒有限制。創(chuàng)建聯(lián)結(jié)的基本規(guī)則也相同。首先列出所有表,然后定義表之間的關(guān)系。例如:
輸入
SELECT prod_name,vend_name,prod_price,quantity FROM orderitems, products,vendors WHERE products.vend_id = vendors.vend_id AND orderitems.prod_id = products.prod_id AND order_num = 20005;
輸出

分析
?此例子顯示編號(hào)為20005的訂單中的物品。訂單物品存儲(chǔ)在orderitems表中。每個(gè)產(chǎn)品按其產(chǎn)品ID存儲(chǔ),它引用products表中的產(chǎn)品。這些產(chǎn)品通過供應(yīng)商ID聯(lián)結(jié)到vendors表中相應(yīng)的供應(yīng)商,供應(yīng)商ID存儲(chǔ)在每個(gè)產(chǎn)品的記錄中。這里的FROM子句列出了3個(gè)表,而WHERE子句定義了這兩個(gè)聯(lián)結(jié)條件,而第三個(gè)聯(lián)結(jié)條件用來過濾出訂單20005中的物品。
如何鞏固學(xué)習(xí)
提示:在學(xué)習(xí)的過程中,我們需要先自行進(jìn)行思考,而不是一遇到不會(huì)的就放棄思考直接看答案,如果最后遇到真的不會(huì)的題目,我們可以適當(dāng)?shù)倪M(jìn)行觀看答案,看自己的思路是否正確,在作出正確的判斷
本文小結(jié)
聯(lián)結(jié)是SQL中最重要最強(qiáng)大的特性,有效地使用聯(lián)結(jié)需要對(duì)關(guān)系數(shù)據(jù)庫設(shè)計(jì)有基本的了解。本章隨著對(duì)聯(lián)結(jié)的介紹講述了關(guān)系數(shù)據(jù)庫設(shè)計(jì)的一些基本知識(shí),包括等值聯(lián)結(jié)(也稱為內(nèi)部聯(lián)結(jié)) 這種最經(jīng)常使用的聯(lián)結(jié)形式。下一篇文章將介紹如何創(chuàng)建其他類型的聯(lián)結(jié)
總結(jié)
到此這篇關(guān)于MySQL聯(lián)結(jié)表介紹以及使用的文章就介紹到這了,更多相關(guān)MySQL聯(lián)結(jié)表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL添加外鍵時(shí)報(bào)錯(cuò):1215 Cannot add the foreign key constraint的解決方法
大家都知道MySQL中經(jīng)常會(huì)需要?jiǎng)?chuàng)建父子表之間的約束,這個(gè)約束是需要建立在主外鍵基礎(chǔ)之上的,最近在MySQL添加外鍵時(shí)發(fā)現(xiàn)了一個(gè)報(bào)錯(cuò):1215 Cannot add the foreign key constraint,所以這篇文章就給大家介紹了如何解決在創(chuàng)建主外鍵約束過程中碰到的這個(gè)問題。2016-11-11
在同一臺(tái)機(jī)器上運(yùn)行多個(gè) MySQL 服務(wù)
在同一臺(tái)機(jī)器上運(yùn)行多個(gè) MySQL 服務(wù)...2006-11-11
SQLyog錯(cuò)誤號(hào)碼2058最新解決辦法
這篇文章主要給大家介紹了關(guān)于SQLyog錯(cuò)誤號(hào)碼2058的最新解決辦法,使用sqlyog連接數(shù)據(jù)庫過程中可能會(huì)出現(xiàn)2058錯(cuò)誤,出現(xiàn)的原因是因?yàn)镸YSQL8.0對(duì)密碼的加密方式進(jìn)行了改變,需要的朋友可以參考下2023-08-08
MySQL用作備份還原的導(dǎo)入和導(dǎo)出命令用法整理
這篇文章主要介紹了MySQL用作備份還原的導(dǎo)入和導(dǎo)出命令用法整理,包括mysqldump的命令的使用以及l(fā)oad data相關(guān)命令,需要的朋友可以參考下2015-12-12
MySQL pt-query-digest從安裝到實(shí)戰(zhàn)的慢查詢優(yōu)化實(shí)戰(zhàn)指南
本文介紹了pt-query-digest工具的安裝、配置、核心原理和實(shí)戰(zhàn)應(yīng)用,包括慢查詢分析步驟、常見場景命令模板及使用技巧,通過合理配置和分析,能夠有效提升MySQL性能,感興趣的朋友跟隨小編一起看看吧2026-04-04
解決mysql報(bào)錯(cuò)ERROR 1049 (42000): Unknown dat
對(duì)于錯(cuò)誤代碼1049(42000):Unknown database ‘?dāng)?shù)據(jù)庫‘,這個(gè)錯(cuò)誤通常表示您正在嘗試訪問一個(gè)不存在的數(shù)據(jù)庫,本文給出了解決方法,您可以按照文中步驟進(jìn)行操作,需要的朋友可以參考下2024-01-01

