圖解 SQL,這也太秀了吧!
點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)
真香!24W字的Java面試手冊(cè)(點(diǎn)擊查看)
原文鏈接:https://blog.csdn.net/horses/article/details/104553075
在計(jì)算機(jī)領(lǐng)域有許多偉大的設(shè)計(jì)理念和思想,例如:
在 Unix 中,一切皆文件。
在面向?qū)ο蟮木幊陶Z(yǔ)言中,一切皆對(duì)象。
關(guān)系數(shù)據(jù)庫(kù)同樣也有自己的設(shè)計(jì)思想:在 SQL 中,一切皆關(guān)系。
關(guān)系模型

關(guān)系模型由數(shù)據(jù)結(jié)構(gòu)、關(guān)系操作、完整性約束三部分組成。
關(guān)系模型中的數(shù)據(jù)結(jié)構(gòu)就是關(guān)系表,包括基礎(chǔ)表、派生表(查詢(xún)結(jié)果)和虛擬表(視圖)。
完整性約束用于維護(hù)數(shù)據(jù)的完整性或者滿足業(yè)務(wù)約束的需求,包括實(shí)體完整性(主鍵約束)、參照完整性(外鍵約束)以及用戶(hù)定義的完整性(非空約束、唯一約束、檢查約束和默認(rèn)值)。我們今天的主題是關(guān)系操作語(yǔ)言,也就是 SQL。本文使用的示例數(shù)據(jù)來(lái)源于:https://blog.csdn.net/horses/article/details/86518676
面向集合
SQL(結(jié)構(gòu)化查詢(xún)語(yǔ)言)是操作關(guān)系數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)語(yǔ)言。SQL 非常接近英語(yǔ),使用起來(lái)非常簡(jiǎn)單。它在設(shè)計(jì)之初就考慮了非技術(shù)人員的使用需求,我們通常只需說(shuō)明想要的結(jié)果(What),而將數(shù)據(jù)處理的過(guò)程(How)交給數(shù)據(jù)庫(kù)管理系統(tǒng)。所以說(shuō),SQL 才是真正給人用的編程語(yǔ)言!??
接下來(lái)我們具體分析一下關(guān)系的各種操作語(yǔ)句;目的是為了讓大家能夠了解 SQL 是一種面向集合的編程語(yǔ)言,它的操作對(duì)象是集合,操作的結(jié)果也是集合。
??在關(guān)系數(shù)據(jù)庫(kù)中,關(guān)系、表、集合三者通常表示相同的概念。
SELECT
下面是一個(gè)簡(jiǎn)單的查詢(xún)語(yǔ)句:
SELECT employee_id, first_name, last_name, hire_date
FROM employees;它的作用就是從 employees 表中查詢(xún)員工信息。顯然,我們都知道 FROM 之后是一個(gè)表(關(guān)系、集合)。不僅如此,整個(gè)查詢(xún)語(yǔ)句的結(jié)果也是一個(gè)表。所以,我們可以將上面的查詢(xún)作為表使用:
SELECT *
FROM (SELECT employee_id, first_name, last_name, hire_date
FROM employees) t;括號(hào)內(nèi)的查詢(xún)語(yǔ)句被稱(chēng)為派生表,我們給它指定了一個(gè)別名叫做 t。同樣,整個(gè)查詢(xún)結(jié)果也是一個(gè)表;這就意味著我們可以繼續(xù)嵌套,雖然這么做很無(wú)聊。
我們?cè)倏匆粋€(gè) PostgreSQL 中的示例:
-- PostgreSQL
SELECT *
FROM upper('sql');
| upper |
|-------|
| SQL |
upper() 是一個(gè)大寫(xiě)轉(zhuǎn)換的函數(shù)。它出現(xiàn)再 FROM 子句中,意味著它的結(jié)果也是一個(gè)表,只不過(guò)是 1 行 1 列的特殊表。
SELECT 子句用于指定需要查詢(xún)的字段,可以包含表達(dá)式、函數(shù)值等。SELECT 在關(guān)系操作中被稱(chēng)為投影(Projection),看下面的示意圖應(yīng)該就比較好理解了。

除了 SELECT 之外,還有一些常用的 SQL 子句。
WHERE 用于指定數(shù)據(jù)過(guò)濾的條件,在關(guān)系運(yùn)算中被稱(chēng)為選擇(Selection),示意圖如下:

ORDER BY 用于對(duì)查詢(xún)的結(jié)果進(jìn)行排序,示意圖如下:

總之,SQL 可以完成各種數(shù)據(jù)操作,例如過(guò)濾、分組、排序、限定數(shù)量等;所有這些操作的對(duì)象都是關(guān)系表,結(jié)果也是關(guān)系表。

在這些關(guān)系操作中,有一個(gè)比較特殊,就是分組。
GROUP BY
分組( GROUP BY)操作和其他的關(guān)系操作不同,因?yàn)樗淖兞岁P(guān)系的結(jié)構(gòu)。來(lái)看下面的示例:
SELECT department_id, count(*), first_name
FROM employees
GROUP BY department_id;所以說(shuō),GROUP BY 改變了集合元素(數(shù)據(jù)行)的結(jié)構(gòu),創(chuàng)建了一個(gè)全新的關(guān)系。分組操作的示意圖如下:
盡管如此,GROUP BY 的結(jié)果仍然是一個(gè)集合。
UNION
SQL 面向集合特性最明顯的體現(xiàn)就是 UNION(并集運(yùn)算)、INTERSECT(交集運(yùn)算)和 EXCEPT/MINUS(差集運(yùn)算)。
這些集合運(yùn)算符的作用都是將兩個(gè)集合并成一個(gè)集合,因此需要滿足以下條件:
兩邊的集合中字段的數(shù)量和順序必須相同;
兩邊的集合中對(duì)應(yīng)字段的類(lèi)型必須匹配或兼容。
具體來(lái)說(shuō),UNION 和 UNION ALL 用于計(jì)算兩個(gè)集合的并集,返回出現(xiàn)在第一個(gè)查詢(xún)結(jié)果或者第二個(gè)查詢(xún)結(jié)果中的數(shù)據(jù)。它們的區(qū)別在于 UNION 排除了結(jié)果中的重復(fù)數(shù)據(jù),UNION ALL 保留了重復(fù)數(shù)據(jù)。下面是 UNION 操作的示意圖:

INTERSECT 操作符用于返回兩個(gè)集合中的共同部分,即同時(shí)出現(xiàn)在第一個(gè)查詢(xún)結(jié)果和第二個(gè)查詢(xún)結(jié)果中的數(shù)據(jù),并且排除了結(jié)果中的重復(fù)數(shù)據(jù)。INTERSECT 運(yùn)算的示意圖如下:

EXCEPT 或者 MINUS 操作符用于返回兩個(gè)集合的差集,即出現(xiàn)在第一個(gè)查詢(xún)結(jié)果中,但不在第二個(gè)查詢(xún)結(jié)果中的記錄,并且排除了結(jié)果中的重復(fù)數(shù)據(jù)。EXCEPT 運(yùn)算符的示意圖如下:

除此之外,DISTINCT 運(yùn)算符用于消除重復(fù)數(shù)據(jù),也就是排除集合中的重復(fù)元素。
??SQL 中的關(guān)系概念來(lái)自數(shù)學(xué)中的集合理論,因此 UNION、INTERSECT 和 EXCEPT 分別來(lái)自集合論中的并集(∪ \cup∪)、交集(∩ \cap∩)和差集(? \setminus?)運(yùn)算。需要注意的是,集合理論中的集合不允許存在重復(fù)的數(shù)據(jù),但是 SQL 允許。因此,SQL 中的集合也被稱(chēng)為多重集合(multiset);多重集合與集合理論中的集合都是無(wú)序的,但是 SQL 可以通過(guò) ORDER BY 子句對(duì)查詢(xún)結(jié)果進(jìn)行排序。
JOIN
常見(jiàn)的 SQL連接查類(lèi)型包括內(nèi)連接、外連接、交叉連接等。其中,外連接又可以分為左外連接、右外連接以及全外連接。
內(nèi)連接(Inner Join)返回兩個(gè)表中滿足連接條件的數(shù)據(jù),內(nèi)連接的原理如下圖所示:

左外連接(Left Outer Join)返回左表中所有的數(shù)據(jù);對(duì)于右表,返回滿足連接條件的數(shù)據(jù);如果沒(méi)有就返回空值。左外連接的原理如下圖所示:

右外連接(Right Outer Join)返回右表中所有的數(shù)據(jù);對(duì)于左表,返回滿足連接條件的數(shù)據(jù),如果沒(méi)有就返回空值。右外連接與左外連接可以互換,以下兩者等價(jià):
t1 RIGHT JOIN t2
t2 LEFT JOIN t1
全外連接(Full Outer Join)等價(jià)于左外連接加上右外連接,同時(shí)返回左表和右表中所有的數(shù)據(jù);對(duì)于兩個(gè)表中不滿足連接條件的數(shù)據(jù)返回空值。全外連接的原理如下圖所示:

??其他類(lèi)型的連接還有半連接(SEMI JOIN)、反連接(ANTI JOIN)。
集合操作將兩個(gè)集合合并成一個(gè)更大或更小的集合;連接查詢(xún)將兩個(gè)集合轉(zhuǎn)換成一個(gè)更大或更小的集合,同時(shí)獲得了一個(gè)更大的元素(更多的列)。很多時(shí)候集合操作都可以通過(guò)連接查詢(xún)來(lái)實(shí)現(xiàn),例如:
SELECT department_id
FROM departments
UNION
SELECT department_id
FROM employees;
等價(jià)于:
SELECT COALESCE(d.department_id, e.department_id)
FROM departments d
FULL JOIN employees e ON (e.department_id = d.department_id);我們已經(jīng)介紹了許多查詢(xún)的示例,接下來(lái)看看其他的數(shù)據(jù)操作。
DML
DML 表示數(shù)據(jù)操作語(yǔ)言,也就是插入、更新和刪除。以下是一個(gè)插入語(yǔ)句示例:
CREATE TABLE test(id int);
-- MySQL、SQL Server 等
INSERT INTO test(id) VALUES (1),(2),(3);
-- Oracle
INSERT INTO test(id)
(SELECT 1 AS id FROM DUAL
UNION ALL
SELECT 2 FROM DUAL
UNION ALL
SELECT 3 FROM DUAL);我們通過(guò)一個(gè) INSERT 語(yǔ)句插入了 3 條記錄,或者說(shuō)是插入了一個(gè)包含 3 條記錄的關(guān)系表。因?yàn)椋琔NION ALL 返回的是一個(gè)關(guān)系表。VALUES 同樣是指定了一個(gè)關(guān)系表,在 SQL Server 和 PostgreSQL 中支持以下語(yǔ)句:
SELECT *
FROM (
VALUES(1),(2),(3)
) test(id);
前面我們已經(jīng)說(shuō)過(guò),F(xiàn)ROM 之后是一個(gè)關(guān)系表,所以這里的 VALUES 也是一樣。由于我們經(jīng)常插入單條記錄,并沒(méi)有意識(shí)到實(shí)際上是以表為單位進(jìn)行操作。
同樣,UPDATE 和 DELETE 語(yǔ)句也都是以關(guān)系表為單位的操作;只不過(guò)我們習(xí)慣了說(shuō)更新一行數(shù)據(jù)或者刪除幾條記錄。
如果覺(jué)得文章對(duì)你有用,
如有文章對(duì)你有幫助,
請(qǐng)不要白嫖!
歡迎關(guān)注??、點(diǎn)贊??、轉(zhuǎn)發(fā)??!
推薦, Java面試手冊(cè) 內(nèi)容包括網(wǎng)絡(luò)協(xié)議、Java基礎(chǔ)、進(jìn)階、字符串、集合、并發(fā)、JVM、數(shù)據(jù)結(jié)構(gòu)、算法、MySQL、Redis、Mongo、Spring、SpringBoot、MyBatis、SpringCloud、Linux以及各種中間件(Dubbo、Nginx、Zookeeper、MQ、Kafka、ElasticSearch)等等... 點(diǎn)擊文末“閱讀原文”可直達(dá)


