SQL
序言
雖然我是前端,但我也是想試試看後端的。某次面試,公司要找後端開發,但寫到 SQL 時,我才發現自己對後端最重要的資料庫一無所知。
很明顯,這次面試被打槍了。有沒有人懂非對稱加密怎麼做的(小聲)
要學 SQL 的話,除了自己架資料庫外,SQLZoo 這網站也是個好資源。
2020/03/22 增筆:我最近發現以探案為主題的sql-mysteries也頗好玩:遊戲用生動的故事與查探機制,來教人怎麼用 JOIN 指令,關聯其他的資料。
資料庫資訊
資料庫(Database)下面會有資料表(Table);而資料表的基本架構和表格一樣,以欄與列構成。而這些資料表,都要有一個主鍵(Key value)以資辨識。
關聯式資料庫
在關聯式資料庫(Relational database)的體系下,開發者可以透過資料表的鍵值與外來鍵(Foreign key),與其他的資料表結合。只不過,一個資料表的鍵值,只能對應另一個資料表的外來鍵。如果需要對應多個資料表的外來鍵,也就是被稱為多型關聯(Polymorphic Associations)的東西......我還沒看到解決辦法,但似乎與後端程式語言有關? 🤔
指令備查
以 MySQL/MariaDB 系列指令為準。
SELECT:選取需要的欄位。欄位中間以,分開。例如SELECT name,gdp。FROM:FROM後面要接的是資料表名稱。假設sqlzoo資料庫下面有world資料表的話,可以用:FROM world: 這會在sqlzoo資料庫下面尋找world資料表。FROM sqlzoo.world: 這會在sqlzoo資料庫下面選取world資料表。
WHERE:限定搜尋條件。資料表查找的靈魂。- 可以在
WHERE裡面,用其他資料來查找資料:如WHERE population > (SELECT population FROM world WHERE name='Canada')就是找出所有人口多於Canada的國家。
- 可以在
LEFT( 欄位名稱, 給定字數 ):針對文字欄位,傳回指定數字的字元。例如LEFT( name, 5 )就會給出Afgha,Cuba,Japan,Zimba這樣的字元。=,<>:=是等於、<>是不等於。報告完畢。LIKE:模糊字詞搜尋,而不只有單純的全有全無。%會配對任何字元,包括空白、直到盡頭;_則會配對任何一個字元。- 配對字元放在特定字元前面,就會去查找特定字元前面的字元,反之亦然。
Java%會配對到Java,JavaScript,Java island。%SQL%會配對到MySQL,SQL Server。__SQL會配對到MySQL。
ROUND( 欄位名稱, 初始進位數 ):針對數字欄位,傳回指定的小數。小數取捨為四捨五入。例如 1234.56 這數字:ROUND( 1234.56 ),ROUND( 1234.56, 0 ):1235ROUND( 1234.56, 1 ):1234.6ROUND( 1234.56, 2 ):1234.56ROUND( 1234.56, 4 ):1234.5600ROUND( 1234.56, -1 ):1230ROUND( 1234.56, -2 ):1200
- 邏輯配對「或與非」(
OR,AND,NOT,XOR)。比較特別的是XOR:它會把全都符合與全都不符合過濾掉。 LENGTH( 輸入名稱 ):可以給出該輸入的字串長度。例如LENGTH( name )就會顯示出各國的字串長度Afghanistan 為 11、Austria 為 7 之類的。- 數字欄位可以被計算,例如
gdp/population。 LIMIT 數字:資料庫可能一個條件內有很多資料。如果預期只想抓到幾個資料,可以下LIMIT關鍵字:例如WHERE population > 100000000 LIMIT 3,就會給出三個人口超過 100000000(一億)的國家。ORDER BY:按照某種順序排序。後面能下關鍵字:可以是數字、也可以是羅馬字母。DESC為升序、ASC為降序。
JOIN:與其他資料表作結合,產出的資料表就會同時有兩個資料表的資料了。這個指令需要配合幾個指令:- 首先你要決定用什麼條件,與其他資料表做結合。決定好後,再用
ON來決定這個條件。 - 結合方法
INNER:必須要在前述的兩者吻合時,才收入這筆資料。不吻合的,就會自動不列入。CROSS:以出現順序,無條件結合資料。LEFT:以出現順序,無條件結合資料。不吻合的,以左邊(被結合的)資料表為準。RIGHT:以出現順序,無條件結合資料。不吻合的,以右邊(要結合的)資料表為準。
ON:與其他資料表作結合的依據。如果不下這個指令,則資料表會以出現順序,無條件結合資料(也就是CROSS JOIN);但如果下了,就會按照兩個資料表所指定的數值為結合依據:例如說JOIN something ON something.sid = another.thing的話,資料將比對something的sid和another的thing,並將吻合兩者的欄位,當作是同一筆資料。
- 首先你要決定用什麼條件,與其他資料表做結合。決定好後,再用
INSERT INTO是需要插入數值的指令;而VALUES則是需要插入數值的資料。- 也就是說你會這樣用:
INSERT INTO some VALUES (1,'PIECE');。
- 也就是說你會這樣用:
Nested query & subquery (巢狀查詢與子查詢)
捲毛蔡:「在 SELECT 指令內再放一個 SELECT 指令查詢;通常放在 SELECT 後面的 WHERE 子句,可取得詳細查詢條件。」
-- https://learnsql.com/blog/sql-nested-select/
SELECT * FROM Students WHERE Students.GPA > ( SELECT AVG(Students.GPA) FROM Students );
SELECT AVG(Classes.number_of_students) FROM Classes WHERE Classes.teacher_id IN (
SELECT Teachers.id FROM Teachers WHERE Teachers.subject = 'English' OR Teachers.subject = 'History'
);
People id Name Age 1 Titan 18 2 John 6 3 Alex 40 4 Back 36 5 Deed 22
Marriage id spouse_id 1 5 5 1 3 4 4 3
-- To find someone who is single
SELECT * FROM People WHERE People.id NOT IN ( SELECT Marriage.spouse_id FROM Marriage );
-- Show:
-- id Name Age
-- 2 John 6
correlated or synchronized sub-query (相關子查詢或同步子查詢)
「我們可以在子查詢,參閱外部查詢的數值。我們為表格再命名,便可以分別內外兩個不同的表格。」