👉 本文參考:
文章目錄
1. 數據庫創建與使用 CREATE / USE
CREATE DATABASE test;
USE test;
2. 創建表 CREATE
CREATE TABLE mytable (
# int 類型,不爲空,自增
id INT NOT NULL AUTO_INCREMENT,
# int 類型,不可爲空,默認值爲 1,不爲空
col1 INT NOT NULL DEFAULT 1,
# 變長字符串類型,最長爲 45 個字符,可以爲空
col2 VARCHAR(45) NULL,
# 日期類型,可爲空
col3 DATE NULL,
# 設置主鍵爲 id
PRIMARY KEY (`id`));
3. 修改表 ALTER
# 添加列
ALTER TABLE mytable
ADD col CHAR(20);
# 刪除列
ALTER TABLE mytable
DROP COLUMN col;
# 刪除表
DROP TABLE mytable;
4. 插入 INSERT INTO
# 普通插入
INSERT INTO mytable(col1, col2)
VALUES(val1, val2);
# 插入檢索出來的數據
INSERT INTO mytable1(col1, col2)
SELECT col1, col2
FROM mytable2;
# 將一個表的內容插入到一個新表
CREATE TABLE newtable AS
SELECT * FROM mytable;
5. 更新 UPDATE
UPDATE mytable
SET col = val
WHERE id = 1;
6. 刪除 DELETE
DELETE FROM mytable
WHERE id = 1;
# TRUNCATE TABLE 可以清空表,也就是刪除所有行。
TRUNCATE TABLE mytable;
7. 查詢 SELECT
DISTINCT 去除重複記錄
相同值只會出現一次。它作用於所有列,也就是說所有列的值都相同纔算相同。
SELECT DISTINCT col1, col2
FROM mytable;
LIMIT 限制結果數量子句
限制返回的行數。可以有兩個參數,第一個參數爲起始行,從 0 開始
;第二個參數爲返回的總行數。
# 返回前 5 行:
SELECT *
FROM mytable
LIMIT 5;
SELECT *
FROM mytable
LIMIT 0, 5;
# 返回第 3 ~ 5 行:
SELECT *
FROM mytable
LIMIT 2, 3;
8. 排序 ORDER BY
ASC
:升序(默認)DESC
:降序
可以按多個列進行排序,並且爲每個列指定不同的排序方式:
SELECT *
FROM mytable
ORDER BY col1 DESC, col2 ASC;
9. 通配符 Like
通配符也是用在過濾語句中,但它只能用於文本字段。
% 匹配 >=0 個任意字符
;_ 匹配 ==1 個任意字符
;[ ] 可以匹配集合內的字符
,例如 [ab] 將匹配字符 a 或者 b。用脫字符 ^ 可以對其進行否定
,也就是不匹配集合內的字符。
使用 Like
來進行通配符匹配。
SELECT *
FROM mytable
WHERE col LIKE '[^AB]%'; -- 不以 A 和 B 開頭的任意文本
Copy to clipboardErrorCopied
不要濫用通配符,通配符位於開頭處匹配會非常慢。
10. 計算字段
在數據庫服務器上完成數據的轉換和格式化的工作往往比客戶端上快得多,並且轉換和格式化後的數據量更少的話可以減少網絡通信量。
計算字段通常需要使用 AS
來取別名,否則輸出的時候字段名爲計算表達式。
SELECT col1 * col2 AS alias
FROM mytable;
CONCAT()
用於連接兩個字段。
許多數據庫會使用空格把一個值填充爲列寬,因此連接的結果會出現一些不必要的空格,
使用 TRIM()
可以去除首尾空格。
SELECT CONCAT(TRIM(col1), '(', TRIM(col2), ')') AS concat_col
FROM mytable;
11. 函數
函數
各個 DBMS 的函數都是不相同的,因此不可移植,以下主要是 MySQL 的函數。
AVG()
返回某列的平均值(會忽略 NULL 行)COUNT()
返回某列的行數MAX()
返回某列的最大值MIN()
返回某列的最小值SUM()
返回某列值之和
使用 DISTINCT 可以彙總不同的值。
SELECT AVG(DISTINCT col1) AS avg_col
FROM mytable;
12. 分組 GROUP BY,HAVING
分組:把具有相同的數據值的行放在同一組中。
可以對同一分組數據使用匯總函數進行處理,例如求分組數據的平均值等。
指定的分組字段除了能按該字段進行分組,也會自動按該字段進行排序。
SELECT col, COUNT(*) AS num
FROM mytable
GROUP BY col;
GROUP BY
自動按分組字段進行排序,ORDER BY
也可以按彙總字段來進行排序。
- GROUP BY 子句出現在 WHERE 子句之後,ORDER BY 子句之前;
- 除了彙總字段外,
SELECT 語句中的每一字段都必須在 GROUP BY 子句中給出
;- NULL 的行會單獨分爲一組;
SELECT col, COUNT(*) AS num
FROM mytable
where col > 2
GROUP BY col
ORDER BY num;
WHERE
過濾行,HAVING
過濾分組,行過濾應當先於分組過濾。
having 與 where 功能、用法相同,執行時機不同。
where 在開始時執行檢測數據,對原數據進行過濾。
having 對篩選出的結果再次進行過濾。
having 字段必須是查詢出來的,where 字段必須是數據表存在的。
where 不可以使用字段的別名,having 可以。因爲執行WHERE代碼時,可能尚未確定列值。
where 不可以使用合計函數。一般需用合計函數纔會用 having
SQL標準要求HAVING必須引用GROUP BY子句中的列或用於合計函數中的列
。
SELECT col, COUNT(*) AS num
FROM mytable
WHERE col > 2
GROUP BY col
HAVING num >= 2;
13. 子查詢
子查詢需用括號包裹。
下面的語句可以檢索出客戶的訂單數量,子查詢語句會對第一個查詢檢索出的每個客戶執行一次:
SELECT cust_name, (SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id)
AS orders_num
FROM Customers
ORDER BY cust_name;
FROM 型
from子查詢返回一個表,表型子查詢
。- from後要求是一個表,必須給子查詢結果取個別名。
- 簡化每個查詢內的條件。
- from型需將結果生成一個臨時表格,可用以原表的鎖定的釋放。
select * from (select * from tb where id>0) as subfrom where id>1;
WHERE 型
where子查詢返回一個值,標量子查詢
。- 不需要給子查詢取別名。
- where子查詢內的表,不能直接用以更新。
select * from tb where money = (select max(money) from tb);
- 列子查詢
- 如果子查詢結果返回的是一列,使用
in 或 not in
將子查詢的結果作爲 WHRER 語句的過濾條件 exists 和 not exists
條件,如果子查詢返回數據,則返回1或0。常用於判斷條件。
- 如果子查詢結果返回的是一列,使用
SELECT * FROM mytable1
WHERE col1 IN (SELECT col2 FROM mytable2);
select column1 from t1 where exists (select * from t2);
- 行子查詢
查詢條件是一個行。
行構造符:(col1, col2, …) 或 ROW(col1, col2, …)
行構造符通常用於與對能返回兩個或兩個以上列的子查詢進行比較。
select * from t1 where (id, gender) in (select id, gender from t2);
14. 連接 JOIN ON
連接用於連接多個表,使用 JOIN
關鍵字,並且條件語句使用 ON
而不是 WHERE。
連接可以替換子查詢,並且比子查詢的效率一般會更快。
可以用 AS 給列名、計算字段和表名取別名,給表名取別名是爲了簡化 SQL 語句以及連接相同表。
內連接 INNER JOIN
內連接又稱等值連接,使用 INNER JOIN 關鍵字。
SELECT A.value, B.value
FROM tablea AS A INNER JOIN tableb AS B
ON A.key = B.key;
等同於
SELECT A.value, B.value
FROM tablea AS A, tableb AS B
WHERE A.key = B.key;
自連接 INNER JOIN
自連接可以看成內連接的一種,只是連接的表是自身而已。
一張員工表,包含員工姓名和員工所屬部門,要找出與 Jim 處在同一部門的所有員工姓名。
- 子查詢版本
SELECT name FROM employee
WHERE department = (
SELECT department
FROM employee
WHERE name = "Jim");
- 自連接版本
SELECT e1.name
FROM employee AS e1 INNER JOIN employee AS e2
ON e1.department = e2.department
AND e2.name = "Jim";
外連接 LEFT/RIGHT OUTER JOIN
外連接保留了沒有關聯的那些行。
- 左外連接(保留左表所有行)
- 右外連接
- 全外連接
檢索所有顧客的訂單信息,包括還沒有訂單信息的顧客。
SELECT Customers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
15. 組合查詢 UNION
-
使用 UNION 來組合兩個查詢,如果第一個查詢返回 M 行,第二個查詢返回 N 行,那麼組合查詢的結果一般爲 M+N 行。
-
每個查詢必須包含相同的列、表達式和聚集函數。
-
默認會去除相同行,如果需要保留相同行,使用 UNION ALL。
-
只能包含一個 ORDER BY 子句,並且必須位於語句的最後。
SELECT col FROM mytable WHERE col = 1
UNION
SELECT col FROM mytable WHERE col =2;
16. 視圖 VIEW
視圖是虛擬的表,本身不包含數據,也就不能對其進行索引操作。
對視圖的操作和對普通表的操作一樣。
視圖具有如下好處:
- 簡化複雜的 SQL 操作,比如複雜的連接;
- 只使用實際表的一部分數據;
- 通過只給用戶訪問視圖的權限,保證數據的安全性;
- 更改數據格式和表示。
CREATE VIEW myview AS
SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col
FROM mytable
WHERE col5 = val;
17. 存儲過程 PROCEDURE
存儲過程可以看成是對一系列 SQL 操作的批處理。
使用存儲過程的好處:
- 代碼封裝,保證了一定的安全性;
- 代碼複用;
- 由於是預先編譯,因此具有很高的性能。
不帶參數的存儲過程
create procedure GetUsers()
begin
select * from users;
end;
調用:
call GetUsers();
刪除:
drop procedure if exists GetUsers;
帶參數的存儲過程
命令行中創建存儲過程需要使用 delimeter
自定義分隔符,因爲命令行是以 ; 爲結束符,而存儲過程中也包含了分號,因此會錯誤把這部分分號當成是結束符,造成語法錯誤。
包含 in、out 和 inout 三種參數。
IN
輸入:在調用過程中,將數據輸入到過程體內部的參數OUT
輸出:在調用過程中,將過程體處理完的結果返回到客戶端INOUT
輸入輸出:既可輸入,也可輸出
給變量賦值都需要用 select into
語句。
每次只能給一個變量賦值,不支持集合的操作。
示例:輸入一個用戶ID,返回該用戶的名字
# 自定義結束符號
delimiter //
create procedure GetNameByID(
in userID int
out userName varchar(200))
begin
select name from user
where id = userID
into userName;
end //
# 修改結束符號爲原來的分號
delimiter ;
調用:MySQL 中變量都必須以 @ 開始
call GetNameByID(1,@userName)
select @userName;
18. 觸發器 TRIGGER
觸發器會在某個表執行以下語句時而自動執行:DELETE、INSERT、UPDATE。
觸發器必須指定在語句執行之前還是之後自動執行,之前執行使用 BEFORE 關鍵字,之後執行使用 AFTER 關鍵字。BEFORE
用於數據驗證和淨化,AFTER
用於審計跟蹤,將修改記錄到另外一張表中。
INSERT
觸發器包含一個名爲 NEW 的虛擬表。DELETE
觸發器包含一個名爲 OLD 的虛擬表,並且是隻讀的。UPDATE
觸發器包含一個名爲 NEW 和一個名爲 OLD 的虛擬表,其中 NEW 是可以被修改的,而 OLD 是隻讀的。
創建觸發器
CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt
參數:
- trigger_time 是觸發程序的動作時間。它可以是 before 或 after,以指明觸發程序是在激活它的語句之前或之後觸發。
- trigger_event 指明瞭激活觸發程序的語句的類型
- INSERT:將新行插入表時激活觸發程序
- UPDATE:更改某一行時激活觸發程序
- DELETE:從表中刪除某一行時激活觸發程序
- tbl_name:監聽的表,必須是永久性的表,不能將觸發程序與TEMPORARY表或視圖關聯起來。
- trigger_stmt:當觸發程序激活時執行的語句。執行多個語句,可使用 BEGIN…END 複合語句結構
CREATE TRIGGER mytrigger AFTER INSERT ON mytable FOR EACH ROW SELECT NEW.col into @result;
刪除觸發器
DROP TRIGGER trigger_name