MySQL 高級(進階) SQL 語句 use gy; create table location (Region char(20),Store_Name char(20)); insert into location values('East','Boston'); insert into loc ...
use gy;
create table location (Region char(20),Store_Name char(20));
insert into location values('East','Boston');
insert into location values('East','New York');
insert into location values('West','Los Angeles');
insert into location values('West','Houston');
create table store_info (Store_Name char(20),Sales int(10),Date char(10));
insert into store_info values('Los Angeles','1500','2020-12-05');
insert into store_info values('Houston','250','2020-12-07');
insert into store_info values('Los Angeles','300','2020-12-08');
insert into store_info values('Boston','700','2020-12-08');
---- SELECT ----顯示表格中一個或數個欄位的所有數據記錄 語法:SELECT "欄位" FROM "表名";
SELECT Store_Name FROM Store_Info;
---- DISTINCT ----不顯示重覆的數據記錄 語法:
SELECT DISTINCT Store_Name FROM Store_Info;
---- WHERE ----有條件查詢 語法:SELECT "欄位" FROM "表名" WHERE "條件";
SELECT Store_Name FROM Store_Info WHERE Sales > 1000;
---- AND OR ----且 或 語法:SELECT "欄位" FROM "表名" WHERE "條件1" {[AND|OR] "條件2"}+ ;
SELECT Store_Name FROM Store_Info WHERE Sales > 1000 OR (Sales < 500 AND Sales > 200);
---- IN ----顯示已知的值的數據記錄 語法:SELECT "欄位" FROM "表名" WHERE "欄位" IN ('值1', '值2', ...);
SELECT * FROM Store_Info WHERE Store_Name IN ('Los Angeles', 'Houston');
---- BETWEEN ----顯示兩個值範圍內的數據記錄 語法:SELECT "欄位" FROM "表名" WHERE "欄位" BETWEEN '值1' AND '值2';
SELECT * FROM Store_Info WHERE Date BETWEEN '2020-12-06' AND '2020-12-10';
---- 通配符 ----通常通配符都是跟 LIKE 一起使用的 % :百分號表示零個、一個或多個字元 _ :下劃線表示單個字元
'A_Z':所有以 'A' 起頭,另一個任何值的字元,且以 'Z' 為結尾的字元串。例如,'ABZ' 和 'A2Z' 都符合這一個模式,而 'AKKZ' 並不符合 (因為在 A 和 Z 之間有兩個字元,而不是一個字元)。
'ABC%': 所有以 'ABC' 起頭的字元串。例如,'ABCD' 和 'ABCABC' 都符合這個模式。
'%XYZ': 所有以 'XYZ' 結尾的字元串。例如,'WXYZ' 和 'ZZXYZ' 都符合這個模式。
'%AN%': 所有含有 'AN'這個模式的字元串。例如,'LOS ANGELES' 和 'SAN FRANCISCO' 都符合這個模式。
'_AN%':所有第二個字母為 'A' 和第三個字母為 'N' 的字元串。例如,'SAN FRANCISCO' 符合這個模式,而 'LOS ANGELES' 則不符合這個模式。
---- LIKE ----匹配一個模式來找出我們要的數據記錄 語法:SELECT "欄位" FROM "表名" WHERE "欄位" LIKE {模式};
SELECT * FROM Store_Info WHERE Store_Name like '%os%';
---- ORDER BY ----按關鍵字排序 語法:SELECT "欄位" FROM "表名" [WHERE "條件"] ORDER BY "欄位" [ASC, DESC];
#ASC 是按照升序進行排序的,是預設的排序方式。 #DESC 是按降序方式進行排序。
SELECT Store_Name,Sales,Date FROM Store_Info ORDER BY Sales DESC;
---- 函數 ----
數學函數: abs(x) 返回 x 的絕對值 rand() 返回 0 到 1 的隨機數 mod(x,y) 返回 x 除以 y 以後的餘數 power(x,y) 返回 x 的 y 次方 round(x) 返回離 x 最近的整數 round(x,y) 保留 x 的 y 位小數四捨五入後的值 sqrt(x) 返回 x 的平方根 truncate(x,y) 返回數字 x 截斷為 y 位小數的值 ceil(x) 返回大於或等於 x 的最小整數 floor(x) 返回小於或等於 x 的最大整數 greatest(x1,x2...) 返回集合中最大的值,也可以返回多個欄位的最大的值 least(x1,x2...) 返回集合中最小的值,也可以返回多個欄位的最小的值
示例:
SELECT abs(-1), rand(), mod(5,3), power(2,3), round(1.89);
SELECT round(1.8937,3), truncate(1.235,2), ceil(5.2), floor(2.1), least(1.89,3,6.1,2.1);
聚合函數: avg() 返回指定列的平均值 count() 返回指定列中非 NULL 值的個數 min() 返回指定列的最小值 max() 返回指定列的最大值 sum(x) 返回指定列的所有值之和
SELECT avg(Sales) FROM Store_Info;
SELECT count(Store_Name) FROM Store_Info;
SELECT count(DISTINCT Store_Name) FROM Store_Info;
SELECT max(Sales) FROM Store_Info;
SELECT min(Sales) FROM Store_Info;
SELECT sum(Sales) FROM Store_Info;
City 表格 +----------+
name |
---|
beijing |
nanjing |
shanghai |
<null> |
<null> |
+----------+
SELECT count(name) FROM City;
SELECT count(*) FROM City;
#count(*) 包括了所有的列的行數,在統計結果的時候,不會忽略列值為 NULL
#count(列名) 只包括列名那一列的行數,在統計結果的時候,會忽略列值為 NULL 的行
字元串函數: trim() 返回去除指定格式的值 concat(x,y) 將提供的參數 x 和 y 拼接成一個字元串 substr(x,y) 獲取從字元串 x 中的第 y 個位置開始的字元串,跟substring()函數作用相同 substr(x,y,z) 獲取從字元串 x 中的第 y 個位置開始長度為 z 的字元串 length(x) 返回字元串 x 的長度 replace(x,y,z) 將字元串 z 替代字元串 x 中的字元串 y upper(x) 將字元串 x 的所有字母變成大寫字母 lower(x) 將字元串 x 的所有字母變成小寫字母 left(x,y) 返回字元串 x 的前 y 個字元 right(x,y) 返回字元串 x 的後 y 個字元 repeat(x,y) 將字元串 x 重覆 y 次 space(x) 返回 x 個空格 strcmp(x,y) 比較 x 和 y,返回的值可以為-1,0,1 reverse(x) 將字元串 x 反轉
SELECT concat(Region, Store_Name) FROM location WHERE Store_Name = 'Boston';
#如sql_mode開啟了PIPES_AS_CONCAT,"||"視為字元串的連接操作符而非或運算符,和字元串的拼接函數Concat相類似,這和Oracle資料庫使用方法一樣的
SELECT Region || ' ' || Store_Name FROM location WHERE Store_Name = 'Boston';
SELECT substr(Store_Name,3) FROM location WHERE Store_Name = 'Los Angeles';
SELECT substr(Store_Name,2,4) FROM location WHERE Store_Name = 'New York';
SELECT TRIM ([ [位置] [要移除的字元串] FROM ] 字元串);
#[位置]:的值可以為 LEADING (起頭), TRAILING (結尾), BOTH (起頭及結尾)。 #[要移除的字元串]:從字串的起頭、結尾,或起頭及結尾移除的字元串。預設時為空格。
SELECT TRIM(LEADING 'Ne' FROM 'New York');
SELECT Region,length(Store_Name) FROM location;
SELECT REPLACE(Region,'ast','astern')FROM location;
---- GROUP BY ----對GROUP BY後面的欄位的查詢結果進行彙總分組,通常是結合聚合函數一起使用的 GROUP BY 有一個原則,凡是在 GROUP BY 後面出現的欄位,必須在 SELECT 後面出現; 凡是在 SELECT 後面出現的、且未在聚合函數中出現的欄位,必須出現在 GROUP BY 後面
語法:SELECT "欄位1", SUM("欄位2") FROM "表名" GROUP BY "欄位1";
SELECT Store_Name, SUM(Sales) FROM Store_Info GROUP BY Store_Name ORDER BY sales desc;
---- HAVING ----用來過濾由 GROUP BY 語句返回的記錄集,通常與 GROUP BY 語句聯合使用 HAVING 語句的存在彌補了 WHERE 關鍵字不能與聚合函數聯合使用的不足。 語法:SELECT "欄位1", SUM("欄位2") FROM "表格名" GROUP BY "欄位1" HAVING (函數條件);
SELECT Store_Name, SUM(Sales) FROM Store_Info GROUP BY Store_Name HAVING SUM(Sales) > 1500;
---- 別名 ----欄位別名 表格別名 語法:SELECT "表格別名"."欄位1" [AS] "欄位別名" FROM "表格名" [AS] "表格別名";
SELECT A.Store_Name Store, SUM(A.Sales) "Total Sales" FROM Store_Info A GROUP BY A.Store_Name;
---- 子查詢 ----連接表格,在WHERE 子句或 HAVING 子句中插入另一個 SQL 語句 語法:SELECT "欄位1" FROM "表格1" WHERE "欄位2" [比較運算符] #外查詢
(SELECT "欄位1" FROM "表格2" WHERE "條件"); #內查詢
#可以是符號的運算符,例如 =、>、<、>=、<= ;也可以是文字的運算符,例如 LIKE、IN、BETWEEN
SELECT SUM(Sales) FROM Store_Info WHERE Store_Name IN
(SELECT Store_Name FROM location WHERE Region = 'West');
SELECT SUM(A.Sales) FROM store_info A WHERE A.Store_Name IN
(SELECT Store_Name FROM location B WHERE B.Store_Name = A.Store_Name);
---- EXISTS ----用來測試內查詢有沒有產生任何結果,類似布爾值是否為真 #如果有的話,系統就會執行外查詢中的SQL語句。若是沒有的話,那整個 SQL 語句就不會產生任何結果。 語法:SELECT "欄位1" FROM "表格1" WHERE EXISTS (SELECT * FROM "表格2" WHERE "條件");
SELECT SUM(Sales) FROM Store_Info WHERE EXISTS (SELECT * FROM location WHERE Region = 'West');
---- 連接查詢 ---- location 表格 +----------+--------------+ | Region | Store_Name | |----------+--------------| | East | Boston | | East | New York | | West | Los Angeles | | West | Houston | +----------+--------------+
UPDATE Store_Info SET store_name='Washington' WHERE sales=300;
Store_Info 表格 +--------------+---------+------------+ | Store_Name | Sales | Date | |--------------+---------+------------| | Los Angeles | 1500 | 2020-12-05 | | Houston | 250 | 2020-12-07 | | Washington | 300 | 2020-12-08 | | Boston | 700 | 2020-12-08 | +--------------+---------+------------+
inner join(內連接):只返回兩個表中聯結欄位相等的行 left join(左連接):返回包括左表中的所有記錄和右表中聯結欄位相等的記錄 right join(右連接):返回包括右表中的所有記錄和左表中聯結欄位相等的記錄
SELECT * FROM location A RIGHT JOIN Store_Info B on A.Store_Name = B.Store_Name ;
SELECT * FROM location A LEFT JOIN Store_Info B on A.Store_Name = B.Store_Name ;
內連接一:
SELECT * FROM location A INNER JOIN Store_Info B on A.Store_Name = B.Store_Name ;
內連接二:
SELECT * FROM location A, Store_Info B WHERE A.Store_Name = B.Store_Name;
SELECT A.Region REGION, SUM(B.Sales) SALES FROM location A, Store_Info B
WHERE A.Store_Name = B.Store_Name GROUP BY REGION;
自我連接,算排名: +----------+-------+ | name | score | +----------+-------+ | lisi | 100 | | zhaoliu | 90 | | wangwu | 80 | | zhangsan | 70 | +----------+-------+
分組彙總後統計 score 欄位的值是比自己本身的值小的以及 score 欄位 和 name 欄位都相同的數量
SELECT A.name, A.score, count(B.score) rank FROM class A, class B
WHERE A.score < B.score OR (A.score = B.score AND A.Name = B.Name)
GROUP BY A.name, A.score ORDER BY rank;
---- CREATE VIEW ----視圖,可以被當作是虛擬表或存儲查詢。 視圖跟表格的不同是,表格中有實際儲存數據記錄,而視圖是建立在表格之上的一個架構,它本身並不實際儲存數據記錄。 臨時表在用戶退出或同資料庫的連接斷開後就自動消失了,而視圖不會消失。 視圖不含有數據,只存儲它的定義,它的用途一般可以簡化複雜的查詢。比如你要對幾個表進行連接查詢,而且還要進行統計排序等操作,寫SQL語句會很麻煩的,用視圖將幾個表聯結起來,然後對這個視圖進行查詢操作,就和對一個表查詢一樣,很方便。
語法:CREATE VIEW "視圖表名" AS "SELECT 語句";
CREATE VIEW V_REGION_SALES AS SELECT A.Region REGION,SUM(B.Sales) SALES FROM location A
INNER JOIN Store_Info B ON A.Store_Name = B.Store_Name GROUP BY REGION;
SELECT * FROM V_REGION_SALES;
DROP VIEW V_REGION_SALES;
---- UNION ----聯集,將兩個SQL語句的結果合併起來,兩個SQL語句所產生的欄位需要是同樣的數據記錄種類 UNION :生成結果的數據記錄值將沒有重覆,且按照欄位的順序進行排序 語法:[SELECT 語句 1] UNION [SELECT 語句 2];
UNION ALL :將生成結果的數據記錄值都列出來,無論有無重覆 語法:[SELECT 語句 1] UNION ALL [SELECT 語句 2];
SELECT Store_Name FROM location UNION SELECT Store_Name FROM Store_Info;
SELECT Store_Name FROM location UNION ALL SELECT Store_Name FROM Store_Info;
---- 交集值 ----取兩個SQL語句結果的交集
SELECT A.Store_Name FROM location A INNER JOIN Store_Info B ON A.Store_Name = B.Store_Name;
SELECT A.Store_Name FROM location A INNER JOIN Store_Info B USING(Store_Name);
#取兩個SQL語句結果的交集,且沒有重覆
SELECT DISTINCT A.Store_Name FROM location A INNER JOIN Store_Info B USING(Store_Name);
SELECT DISTINCT Store_Name FROM location WHERE (Store_Name) IN (SELECT Store_Name FROM Store_Info);
SELECT DISTINCT A.Store_Name FROM location A LEFT JOIN Store_Info B USING(Store_Name) WHERE B.Store_Name IS NOT NULL;
SELECT A.Store_Name FROM (SELECT B.Store_Name FROM location B INNER JOIN Store_Info C ON B.Store_Name = C.Store_Name) A
GROUP BY A.Store_Name;
SELECT A.Store_Name FROM
(SELECT DISTINCT Store_Name FROM location UNION ALL SELECT DISTINCT Store_Name FROM Store_Info) A
GROUP BY A.Store_Name HAVING COUNT(*) > 1;
---- 無交集值 ----顯示第一個SQL語句的結果,且與第二個SQL語句沒有交集的結果,且沒有重覆
SELECT DISTINCT Store_Name FROM location WHERE (Store_Name) NOT IN (SELECT Store_Name FROM Store_Info);
SELECT DISTINCT A.Store_Name FROM location A LEFT JOIN Store_Info B USING(Store_Name) WHERE B.Store_Name IS NULL;
SELECT A.Store_Name FROM
(SELECT DISTINCT Store_Name FROM location UNION ALL SELECT DISTINCT Store_Name FROM Store_Info) A
GROUP BY A.Store_Name HAVING COUNT(*) = 1;
---- CASE ----是 SQL 用來做為 IF-THEN-ELSE 之類邏輯的關鍵字 語法:
SELECT CASE ("欄位名")
WHEN "條件1" THEN "結果1"
WHEN "條件2" THEN "結果2"
...
[ELSE "結果N"]
END
FROM "表名";
"條件" 可以是一個數值或是公式。 ELSE 子句則並不是必須的。
SELECT Store_Name, CASE Store_Name
WHEN 'Los Angeles' THEN Sales * 2
WHEN 'Boston' THEN 2000
ELSE Sales
END
"New Sales",Date
FROM Store_Info;
#"New Sales" 是用於 CASE 那個欄位的欄位名。
---- 空值(NULL) 和 無值('') 的區別 ---- 1.無值的長度為 0,不占用空間的;而 NULL 值的長度是 NULL,是占用空間的。 2.IS NULL 或者 IS NOT NULL,是用來判斷欄位是不是為 NULL 或者不是 NULL,不能查出是不是無值的。 3.無值的判斷使用=''或者<>''來處理。<> 代表不等於。 4.在通過 count()指定欄位統計有多少行數時,如果遇到 NULL 值會自動忽略掉,遇到無值會加入到記錄中進行計算。
City 表格 +----------+
name |
---|
beijing |
nanjing |
shanghai |
<null> |
<null> |
shanghai |
+----------+
SELECT length(NULL), length(''), length('1');
SELECT * FROM City WHERE name IS NULL;
SELECT * FROM City WHERE name IS NOT NULL;
SELECT * FROM City WHERE name = '';
SELECT * FROM City WHERE name <> '';
SELECT COUNT(*) FROM City;
SELECT COUNT(name) FROM City;
---- 正則表達式 ---- 匹配模式 描述 實例 ^ 匹配文本的開始字元 ‘^bd’ 匹配以 bd 開頭的字元串 $ 匹配文本的結束字元 ‘qn$’ 匹配以 qn 結尾的字元串 . 匹配任何單個字元 ‘s.t’ 匹配任何 s 和 t 之間有一個字元的字元串
-
匹配零個或多個在它前面的字元 ‘fo*t’ 匹配 t 前面有任意個 o
-
匹配前面的字元 1 次或多次 ‘hom+’ 匹配以 ho 開頭,後面至少一個m 的字元串 字元串 匹配包含指定的字元串 ‘clo’ 匹配含有 clo 的字元串 p1|p2 匹配 p1 或 p2 ‘bg|fg’ 匹配 bg 或者 fg [...] 匹配字元集合中的任意一個字元 ‘[abc]’ 匹配 a 或者 b 或者 c ... 匹配不在括弧中的任何字元 ‘ab’ 匹配不包含 a 或者 b 的字元串 {n} 匹配前面的字元串 n 次 ‘g{2}’ 匹配含有 2 個 g 的字元串 {n,m} 匹配前面的字元串至少 n 次,至多m 次 ‘f{1,3}’ 匹配 f 最少 1 次,最多 3 次
語法:SELECT "欄位" FROM "表名" WHERE "欄位" REGEXP {模式};
SELECT * FROM Store_Info WHERE Store_Name REGEXP 'os';
SELECT * FROM Store_Info WHERE Store_Name REGEXP '^[A-G]';
SELECT * FROM Store_Info WHERE Store_Name REGEXP 'Ho|Bo';
---- 存儲過程 ---- 存儲過程是一組為了完成特定功能的SQL語句集合。
存儲過程在使用過程中是將常用或者複雜的工作預先使用SQL語句寫好並用一個指定的名稱存儲起來,這個過程經編譯和優化後存儲在資料庫伺服器中。當需要使用該存儲過程時,只需要調用它即可。存儲過程在執行上比傳統SQL速度更快、執行效率更高。
存儲過程的優點: 1、執行一次後,會將生成的二進位代碼駐留緩衝區,提高執行效率 2、SQL語句加上控制語句的集合,靈活性高 3、在伺服器端存儲,客戶端調用時,降低網路負載 4、可多次重覆被調用,可隨時修改,不影響客戶端調用 5、可完成所有的資料庫操作,也可控制資料庫的信息訪問許可權
##創建存儲過程##
DELIMITER $$ #將語句的結束符號從分號;臨時改為兩個$$(可以是自定義)
CREATE PROCEDURE Proc() #創建存儲過程,過程名為Proc,不帶參數
-> BEGIN #過程體以關鍵字 BEGIN 開始
-> select * from Store_Info; #過程體語句
-> END $$ #過程體以關鍵字 END 結束
DELIMITER ; #將語句的結束符號恢復為分號
##調用存儲過程##
CALL Proc;
##查看存儲過程##
SHOW CREATE PROCEDURE [資料庫.]存儲過程名; #查看某個存儲過程的具體信息
SHOW CREATE PROCEDURE Proc;
SHOW PROCEDURE STATUS [LIKE '%Proc%'] \G
##存儲過程的參數## IN 輸入參數:表示調用者向過程傳入值(傳入值可以是字面量或變數) OUT 輸出參數:表示過程向調用者傳出值(可以返回多個值)(傳出值只能是變數) INOUT 輸入輸出參數:既表示調用者向過程傳入值,又表示過程向調用者傳出值(值只能是變數)
DELIMITER $$
CREATE PROCEDURE Proc1(IN inname CHAR(16))
-> BEGIN
-> SELECT * FROM Store_Info WHERE Store_Name = inname;
-> END $$
DELIMITER ;
CALL Proc1('Boston');
delimiter $$
mysql> create procedure proc3(in myname char(10), out outname int)
-> begin
-> select sales into outname from t1 where name = myname;
-> end $$
delimiter ;
call proc3('yzh', @out_sales);
select @out_sales;
delimiter $$
mysql> create procedure proc4(inout insales int)
-> begin
-> select count(sales) into insales from t1 where sales < insales;
-> end $$
delimiter ;
set @inout_sales=1000;
call proc4(@inout_sales);
select @inout_sales;
##刪除存儲過程## 存儲過程內容的修改方法是通過刪除原有存儲過程,之後再以相同的名稱創建新的存儲過程。如果要修改存儲過程的名稱,可以先刪除原存儲過程,再以不同的命名創建新的存儲過程。
DROP PROCEDURE IF EXISTS Proc; #僅當存在時刪除,不添加 IF EXISTS 時,如果指定的過程不存在,則產生一個錯誤
##存儲過程的控制語句##
create table t (id int(10));
insert into t values(10);
(1)條件語句if-then-else ···· end if
DELIMITER $$
CREATE PROCEDURE proc2(IN pro int)
-> begin
-> declare var int;
-> set var=pro*2;
-> if var>=10 then
-> update t set id=id+1;
-> else
-> update t set id=id-1;
-> end if;
-> end $$
DELIMITER ;
CALL Proc2(6);
(2)迴圈語句while ···· end while
DELIMITER $$
CREATE PROCEDURE proc3()
-> begin
-> declare var int(10);
-> set var=0;
-> while var<6 do
-> insert into t values(var);
-> set var=var+1;
-> end while;
-> end $$
DELIMITER ;
CALL Proc3;