SQL基本用法總括第二篇,能稍微高級一點點,但是也很常用,
包含:①過濾
②通配符
③計算字段
④函數、子查詢、組合查詢
⑤視圖
⑥存儲過程
⑦遊標
⑧觸發器、事務管理
⑨字符集
⑩權限管理
詳細如下:
一、過濾
where子句可用的操作符
不進行過濾的數據非常大,導致通過網絡傳輸了多餘的數據,從而浪費了網絡帶寬。因此儘量使用 SQL 語句來過濾不必要的數據,而不是傳輸所有的數據到客戶端中然後由客戶端進行過濾。
SELECT *
FROM table_name
WHERE col IS NULL;
操作符 | 說明 |
---|---|
= | 等於 |
< | 小於 |
> | 大於 |
<> != | 不等於 |
<= !> | 小於等於 |
>= !< | 大於等於 |
BETWEEN | 在兩個值之間 |
IS NULL | 爲 NULL 值 |
應該注意到,NULL 與 0、空字符串都不同。
AND 和 OR 用於連接多個過濾條件。優先處理 AND,當一個過濾表達式涉及到多個 AND 和 OR 時,可以使用 () 來決定優先級,使得優先級關係更清晰。
IN 操作符用於匹配一組值,其後也可以接一個 SELECT 子句,從而匹配子查詢得到的一組值。
NOT 操作符用於否定一個條件。
二、 通配符
通配符也是用在過濾語句中,但它只能用於文本字段。
-
% 匹配 >=0 個任意字符;
-
_ 匹配 ==1 個任意字符;
-
[ ] 可以匹配集合內的字符,例如 [ab] 將匹配字符 a 或者 b。用脫字符 ^ 可以對其進行否定,也就是不匹配集合內的字符。
使用 Like 來進行通配符匹配。
SELECT *
FROM table_name
WHERE col LIKE '[^AB]%'; -- 不以 A 和 B 開頭的任意文本
不要濫用通配符,通配符位於開頭處匹配會非常慢。
三、計算字段
在數據庫服務器上完成數據的轉換和格式化的工作往往比客戶端上快得多,並且轉換和格式化後的數據量更少的話可以減少網絡通信量。
計算字段通常需要使用 AS 來取別名,否則輸出的時候字段名爲計算表達式。
SELECT col1 * col2 AS alias
FROM table_name;
CONCAT() 用於連接兩個字段。許多數據庫會使用空格把一個值填充爲列寬,因此連接的結果會出現一些不必要的空格,使用 TRIM() 可以去除首尾空格。
SELECT CONCAT(TRIM(col1), '(', TRIM(col2), ')') AS concat_col
FROM table_name;
四、函數
各個 DBMS 的函數都是不相同的,因此不可移植,以下主要是 MySQL 的函數。
彙總
函 數 | 說 明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
AVG() 會忽略 NULL 行。
使用 DISTINCT 可以彙總不同的值。
SELECT AVG(DISTINCT col1) AS avg_col
FROM table_name;
文本處理
函數 | 說明 |
---|---|
LEFT() | 左邊的字符 |
RIGHT() | 右邊的字符 |
LOWER() | 轉換爲小寫字符 |
UPPER() | 轉換爲大寫字符 |
LTRIM() | 去除左邊的空格 |
RTRIM() | 去除右邊的空格 |
LENGTH() | 長度 |
SOUNDEX() | 轉換爲語音值 |
其中, SOUNDEX() 可以將一個字符串轉換爲描述其語音表示的字母數字模式。
SELECT *
FROM table_name
WHERE SOUNDEX(col1) = SOUNDEX('apple')
日期和時間處理
- 日期格式:YYYY-MM-DD
- 時間格式:HH:MM:SS
函 數 | 說 明 |
---|---|
ADDDATE() | 增加一個日期(天、周等) |
ADDTIME() | 增加一個時間(時、分等) |
CURDATE() | 返回當前日期 |
CURTIME() | 返回當前時間 |
DATE() | 返回日期時間的日期部分 |
DATEDIFF() | 計算兩個日期之差 |
DATE_ADD() | 高度靈活的日期運算函數 |
DATE_FORMAT() | 返回一個格式化的日期或時間串 |
DAY() | 返回一個日期的天數部分 |
DAYOFWEEK() | 對於一個日期,返回對應的星期幾 |
HOUR() | 返回一個時間的小時部分 |
MINUTE() | 返回一個時間的分鐘部分 |
MONTH() | 返回一個日期的月份部分 |
NOW() | 返回當前日期和時間 |
SECOND() | 返回一個時間的秒部分 |
TIME() | 返回一個日期時間的時間部分 |
YEAR() | 返回一個日期的年份部分 |
mysql> SELECT NOW();
2018-4-14 20:25:11
數值處理
函數 | 說明 |
---|---|
SIN() | 正弦 |
COS() | 餘弦 |
TAN() | 正切 |
ABS() | 絕對值 |
SQRT() | 平方根 |
MOD() | 餘數 |
EXP() | 指數 |
PI() | 圓周率 |
RAND() | 隨機數 |
五、子查詢
子查詢中只能返回一個字段的數據。
可以將子查詢的結果作爲 WHRER 語句的過濾條件:
SELECT *
FROM table1_name
WHERE col1 IN (SELECT col2
FROM table2_name);
下面的語句可以檢索出客戶的訂單數量,子查詢語句會對第一個查詢檢索出的每個客戶執行一次:
SELECT cust_name, (SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id)
AS orders_num
FROM Customers
ORDER BY cust_name;
六、組合查詢
使用 UNION 來組合兩個查詢,如果第一個查詢返回 M 行,第二個查詢返回 N 行,那麼組合查詢的結果一般爲 M+N 行。
每個查詢必須包含相同的列、表達式和聚集函數。
默認會去除相同行,如果需要保留相同行,使用 UNION ALL。
只能包含一個 ORDER BY 子句,並且必須位於語句的最後。
SELECT col
FROM mytable
WHERE col = 1
UNION
SELECT col
FROM mytable
WHERE col =2;
七、視圖
視圖是虛擬的表,本身不包含數據,也就不能對其進行索引操作。
對視圖的操作和對普通表的操作一樣。
視圖具有如下好處:
- 簡化複雜的 SQL 操作,比如複雜的連接;
- 只使用實際表的一部分數據;
- 通過只給用戶訪問視圖的權限,保證數據的安全性;
- 更改數據格式和表示。
CREATE VIEW myview AS
SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col
FROM table_name
WHERE col5 = val;
八,存儲過程
存儲過程可以看成是對一系列 SQL 操作的批處理。
使用存儲過程的好處:
- 代碼封裝,保證了一定的安全性;
- 代碼複用;
- 由於是預先編譯,因此具有很高的性能。
命令行中創建存儲過程需要自定義分隔符,因爲命令行是以 ; 爲結束符,而存儲過程中也包含了分號,因此會錯誤把這部分分號當成是結束符,造成語法錯誤。
包含 in、out 和 inout 三種參數。
給變量賦值都需要用 select into 語句。
每次只能給一個變量賦值,不支持集合的操作。
delimiter //
create procedure myprocedure( out ret int )
begin
declare y int;
select sum(col1)
from table_name
into y;
select y*y into ret;
end //
delimiter ;
call myprocedure(@ret);
select @ret;
九、遊標
在存儲過程中使用遊標可以對一個結果集進行移動遍歷。
遊標主要用於交互式應用,其中用戶需要對數據集中的任意行進行瀏覽和修改。
使用遊標的四個步驟:
- 聲明遊標,這個過程沒有實際檢索出數據;
- 打開遊標;
- 取出數據;
- 關閉遊標;
delimiter //
create procedure myprocedure(out ret int)
begin
declare done boolean default 0;
declare mycursor cursor for
select col1 from table_name;
# 定義了一個 continue handler,當 sqlstate '02000' 這個條件出現時,會執行 set done = 1
declare continue handler for sqlstate '02000' set done = 1;
open mycursor;
repeat
fetch mycursor into ret;
select ret;
until done end repeat;
close mycursor;
end //
delimiter ;
十、觸發器
觸發器會在某個表執行以下語句時而自動執行:DELETE、INSERT、UPDATE。
觸發器必須指定在語句執行之前還是之後自動執行,之前執行使用 BEFORE 關鍵字,之後執行使用 AFTER 關鍵字。BEFORE 用於數據驗證和淨化,AFTER 用於審計跟蹤,將修改記錄到另外一張表中。
INSERT 觸發器包含一個名爲 NEW 的虛擬表。
CREATE TRIGGER mytrigger AFTER INSERT ON table_name
FOR EACH ROW SELECT NEW.col into @result;
SELECT @result; -- 獲取結果
DELETE 觸發器包含一個名爲 OLD 的虛擬表,並且是隻讀的。
UPDATE 觸發器包含一個名爲 NEW 和一個名爲 OLD 的虛擬表,其中 NEW 是可以被修改的,而 OLD 是隻讀的。
MySQL 不允許在觸發器中使用 CALL 語句,也就是不能調用存儲過程。
十一、事務管理
基本術語:
- 事務(transaction)指一組 SQL 語句;
- 回退(rollback)指撤銷指定 SQL 語句的過程;
- 提交(commit)指將未存儲的 SQL 語句結果寫入數據庫表;
- 保留點(savepoint)指事務處理中設置的臨時佔位符(placeholder),你可以對它發佈回退(與回退整個事務處理不同)。
不能回退 SELECT 語句,回退 SELECT 語句也沒意義;也不能回退 CREATE 和 DROP 語句。
MySQL 的事務提交默認是隱式提交,每執行一條語句就把這條語句當成一個事務然後進行提交。當出現 START TRANSACTION 語句時,會關閉隱式提交;當 COMMIT 或 ROLLBACK 語句執行後,事務會自動關閉,重新恢復隱式提交。
設置 autocommit 爲 0 可以取消自動提交;autocommit 標記是針對每個連接而不是針對服務器的。
如果沒有設置保留點,ROLLBACK 會回退到 START TRANSACTION 語句處;如果設置了保留點,並且在 ROLLBACK 中指定該保留點,則會回退到該保留點。
START TRANSACTION
// ...
SAVEPOINT delete1
// ...
ROLLBACK TO delete1
// ...
COMMIT
十二、字符集
基本術語:
- 字符集爲字母和符號的集合;
- 編碼爲某個字符集成員的內部表示;
- 校對字符指定如何比較,主要用於排序和分組。
除了給表指定字符集和校對外,也可以給列指定:
CREATE TABLE table_name
(col VARCHAR(10) CHARACTER SET latin COLLATE latin1_general_ci )
DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
可以在排序、分組時指定校對:
SELECT *
FROM table_name
ORDER BY col COLLATE latin1_general_ci;
十三、權限管理
MySQL 的賬戶信息保存在 mysql 這個數據庫中。
USE mysql;
SELECT user FROM user;
創建賬戶
新創建的賬戶沒有任何權限。
CREATE USER myuser IDENTIFIED BY 'mypassword';
修改賬戶名
RENAME USER myuser TO newuser;
刪除賬戶
DROP USER myuser;
查看權限
SHOW GRANTS FOR myuser;
授予權限
賬戶用 username@host 的形式定義,username@% 使用的是默認主機名。
GRANT SELECT, INSERT ON mydatabase.* TO myuser;
刪除權限
GRANT 和 REVOKE 可在幾個層次上控制訪問權限:
- 整個服務器,使用 GRANT ALL 和 REVOKE ALL;
- 整個數據庫,使用 ON database.*;
- 特定的表,使用 ON database.table;
- 特定的列;
- 特定的存儲過程。
REVOKE SELECT, INSERT ON mydatabase.* FROM myuser;
更改密碼
必須使用 Password() 函數進行加密。
SET PASSWROD FOR myuser = Password('new_password');