前言
雖然平時開發中經常接觸MySQL,但大多數的資料庫操作都是通過ORM實現的(SpringDataJPA),自己並沒有從底層接觸SQL。
再加上筆者非專業的身份,對於原生的SQL語句幾乎完全不瞭解。
本文是寫給自己的,關於原生SQL的一篇筆記。
學習應該掌握邊界,由於這部分不是程式設計核心,所以不需要背程式碼,只需要能理解會貼上修改即可。
小Tip:
初學者如何除錯SQL程式碼呢?可以用Navicat或PHPMyAdmin視覺化練習。
先用圖形介面建幾張表,再練習用SQL語句運算元據表即可。
這樣就避免了前期就用純命令列難度過高。
一、增刪改查(CRUD)
在REST規範中寫到:查詢使用GET、增加使用POST、修改使用UPDATE、刪除使用DELETE。增刪改查是最常見的搬磚了,那麼它們的SQL程式碼是什麼呢?
我們先以單表為例(也就是無外來鍵情況)。
單表操作的命令具有很強的規律。包括以下要素:
- 指令
- 欄位
- 目標表
- 引數
- 分號
指令告訴SQL要執行什麼操作,是增加?還是修改?還是刪除?
欄位告訴SQL要操作哪幾個列,比如查出所有學生的姓名和年齡。
目標表告訴SQL要操作哪張表,比如刪除班級表某個班級?
查——SELECT
寫法是:
SELECT 欄位1,欄位2,... FORM 表名 WHERE 條件;
示例:
// 從學生表查詢ID為1的姓名和年齡
SELECT name, age FORM student where id=1;
(輔助記憶:)
此時的指令為SELECT
目標表使用FORM 表名
來確定
引數主要是增加篩選的條件,準確查到想要的資料
分頁查——LIMIT引數(對於MySQL)
寫法是:
SELECT 欄位1,欄位2,... FORM 表名 WHERE 條件 LIMIT 條數;
示例:
// 從學生表查詢10條性別是女的學生的所有欄位
SELECT * FORM student where sex=1 LIMIT 10;
(輔助記憶:)
LIMIT不屬於原生SQL的語法,對於不同的發行版有著不同的實現。
其中MySQL使用的是LIMIT語句,作用是隻取出十條。
這種查詢方法常用於Web的分頁查詢。
增加——INSERT
寫法:
INSERT INTO 表名 (欄位1,欄位2,...) VALUES (值1,值2,...);
示例:
// 向學生表插入姓名為張三、性別為女、年齡20歲的學生
INSERT INTO student (name, sex, age) VALUES (zhangsan, 1, 20);
(輔助記憶:)
對於增加操作,指令就變成了INSERT。
增加操作不僅要給出欄位還要給出值,所以需要VALUES。
此時作用表的字首有一些變化,想象一下:
執行查詢時,資料從資料庫到使用者,所以用FORM;
但插入時,資料從使用者到資料庫,所以是INTO。
而由於插入會直接插到最後一條資料,所以沒有WHERE引數。
修改——UPDATE
寫法:
UPDATE 表名 SET 欄位1=值1,欄位2=值2,欄位3=值3,... WHERE 條件;
示例:
// 在學生表中找到id為1的學生,然後更新姓名=張三、年齡=20、性別=男
UPDATE student SET name=zhangsan,age=20,sex=0,... WHERE id=1;
(輔助記憶:)
此時的指令為UPDATE。
由於需要修改欄位,需要使用SET
修改只針對一條或幾條資料,必須使用WHERE條件進行限制,否則會修改整張表的資料!
刪除——DELETE
DETELE FORM 表名 WHERE 條件;
(輔助記憶:)
刪除的指令為DELETE
由於資料從表中被拿出來,所以是FROM
刪除只針對一條或幾條資料,必須使用WHERE條件進行限制,否則會刪除整張表的資料!
二、WHERE引數
WHERE在SQL定義了查詢條件,但有以下幾個注意的地方:
WHERE搭配的操作符
常規操作符
=
欄位等於值>
欄位大於值<
欄位小於值>=
欄位大於等於值<=
欄位小於等於值
特殊操作符
LIKE
模糊查詢(欄位包含值)IN
屬於(欄位的值屬於給定的集合)BETWEEN
區間(欄位的值屬於給定的區間)
模糊查詢指的是,被查詢的欄位不需要嚴格等於某字串,只需要包含字串即可。
例如,使用LIKE '%zhang%'作為條件,'zhangsan'包括了'zhang',就會被查出來。
模糊查詢又分為三種:
- 字首匹配 開頭必須相同:zhangsan%
- 中綴匹配 中間相同即可:%zhangsan%
- 字尾匹配 結尾必須相同:%zhangsan
WHERE的邏輯運算
在程式語言中一定會用到邏輯用語(與、或、非),而SQL中也有與、或。
邏輯運算子連線兩個條件。
與運算使用AND,表示兩個條件都滿足才有效。
或運算使用OR,表示任一個條件滿足則有效。
實際使用場景可以多個邏輯符連續使用,並用括號定義優先順序。
寫法:
SELECT 欄位 FROM 表名 WHERE 條件1 AND/OR 條件2;
舉例:
// 在學生表取出年齡大於18歲的女生的所有欄位
SELECT * FROM student WHERE sex=1 AND age > 18;
三、多表查詢(連線/JOIN)
軟體開發中常見的實體關係包括:
- 一對一(0…1 : 0…1)
- 一對多/多對一(0…1 : 0…n)
- 多對多(0…n : 0…n)
其中,一對一、一對多、多對一使用外來鍵關聯,而多對多使用中間表關聯。
對於外來鍵關聯的三種情況,在查詢時,往往需要通過table1把與之關聯的table2一併查出來。
這時候可以使用JOIN,把兩張表拼成一張表。
關聯表就像兩個集合,分別是表一和表二,
他們的交集就是兩張表中有外來鍵關聯的那部分記錄。
班級有多個學生,每個學生屬於一個班級。所以學生和班級是多對一。
如果想在查詢學生的時候,一併顯示他們所在班級的資訊:
SELECT student.id, student.name, klass.name, klass.count
FROM Students
INNER JOIN Klass
ON Klass.id=Student.klass_id;
儘管菜鳥教程已經講的很清楚了,我們這裡可以再精簡一些:
- 我們把使用FORM欄位的表定義為左表
- 把使用JOIN欄位的表定義為右表
同樣對於四種連線也可以概況:
- INNER JOIN 一般連線:只查外來鍵關聯的資料,也就是取交集
- LEFT JOIN 左連線:左表全查,右表隨緣,空資料置NULL,也就是取集合A
- RIGHT JOIN 右連線:右表全查,左表隨緣,空資料置NULL,也就是取集合B
- FULL JOIN 全連線:左右表都全查,兩側空資料都置NULL,也就是取並集。
四、總結
藉助程式語言強大的ORM(實體關係對映),增刪改查的操作幾乎不再需要手寫SQL來完成,但我們不能對ORM形成依賴而忘記了原生SQL怎麼寫。
這也是一門必修課,至少能看懂增刪改查的基本寫法,才能在一些特殊需求中知道如何變通,也能在JPA出問題時通過檢視生成的SQL語句來順利的Debug。
文章中提到的內容基本覆蓋日常增刪改查的需要,而對於如何定義主鍵、外來鍵,如何建表、刪表,如何新增、編輯欄位,這些非高頻操作,以後再說。