視圖:VIEW
-
概念
① 虛擬表,本身不存儲數據,可以看做是存儲起來的SELECT語句
② 視圖中SELECT語句中涉及到的表,稱為基表
③ 針對視圖做DML操作,對影響到基表中的數據,反之亦然
④ 創建、刪除視圖本身,不會影響到基表 -
創建視圖
CREATE VIEW view_emp_avg_salary(dept_id, avg_salary) AS SELECT department_id, AVG(salary) FROM employees WHERE department_id IS NOT NULL GROUP BY department_id;
-
查看視圖:
DESC 視圖名;
-
修改視圖
# 方式一 CREATE OR REPLACE VIEW 視圖名 AS SELECT ...#方式二 ALTER VIEW 視圖名 AS SELECT ...
-
刪除視圖
DROP VIEW 視圖名;
索引:INDEX
用于提高查詢性能
存儲過程:PROCEDURE
用于完成一次完整的業務處理,沒有返回值,但可以通過傳出參數將多個值傳給調用者
- 創建
① 無參數無返回值
② 無參數有返回值:# 查詢所有員工信息 DELIMITER $ CREATE PROCEDURE select_all_emp() BEGINSELECT * FROM employees; END $ DELIMITER; # 調用 CALL select_all_emp();
OUT
③ 有參數無返回值:# 查詢員工中的最低工資,并將最低工資輸出到ms DELIMITER $ CREATE PROCEDURE select_min_sal(OUT ms DECIMAL) BEGINSELECT MIN(salary) INTO msFROM employees; END $ DELIMITER; # 調用 CALL select_min_sal(@ms); # 查看參數結果 SELECT @ms;
IN
④ 有參數有返回值:# 查詢指定姓名的員工工資 DELIMITER $ CREATE PROCEDURE show_salary_by_lastname(IN lastName VARCHAR(50)) BEGINSELECT salaryFROM employeesWHERE last_name = lastName; END $ DEIMITER; # 調用 CALL show_salary_by_lastname('Popp');
IN
、OUT
⑤ 有參數有返回值:# 查詢指定姓名的員工工資和部門,并從參數中返回出來 DELIMITER $ CREATE PROCEDURE show_salary_by_lastname2(IN lastName VARCHAR(50), OUT sal DECIMAL, OUT dept_id INT) BEGINSELECT salary,department_id INTO sal, dept_idFROM employeesWHERE last_name = lastName; END $ DELIMITER; # 調用 CALL show_salary_by_lastname2('Popp', @sal, @deptId); # 查詢結果 SELECT @sal, @deptId;
INOUT
# 查詢指定員工的領導姓名,并從參數中返回出來 DELIMITER $ CREATE PROCEDURE show_manager_by_lastname(INOUT lastName VARCHAR(50)) BEGINSELECT m.last_name INTO lastNameFROM employees e JOIN employees mON e.manager_id = m.employee_idWHERE e.last_name = lastName; END $ DELIMITER; # 調用 SET @lastname = 'Popp'; CALL show_manager_by_lastname(@lastname); # 查詢結果 SELECT @lastname;
- characteristics
①LANGUAGE SQL
:表明存儲過程執行體是由SQL語句構成的
②[NOT] DETERMINISTIC
:存儲過程的執行結果是否確定,默認為不確定
③CONTAINS SQL
:存儲過程的執行體包含SQL語句,但不包含讀寫數據的SQL語句,默認是這個
④NO SQL
:存儲過程的執行體不包含任何SQL語句
⑤READS SQL DATA
:存儲過程的執行體包含讀數據的SQL語句
⑥MODIFIES SQL DATA
:存儲過程的執行體包含寫數據的SQL語句
⑦SQL SECURITY {DEFINER | INVOKER}
:執行權限
⑧COMMENT
:備注信息 - 查看創建信息:
SHOW CREATE PRODECURE 存儲過程名稱;
- 查看狀態信息:
SHOW PROCEDURE STATUS LIKE '存儲過程名稱';
- 修改特性
ALTER PROCEDURE '存儲過程名稱' SQL SECURITY INVOKER COMMENT '備注信息...';
- 刪除:
DROP PROCEDURE '存儲過程名稱';
存儲函數:FUNCTION
用于完成一次特定的計算,有一個返回值
# 查詢指定部門的員工人數
DELIMITER $
CREATE FUNCTION select_count_by_dept(dept_id INT)
RETURNS INT
DETERMINISTIC
CONTAINS SQL
READS SQL DATA
BEGINRETURN(SELECT COUNT(*) FROM employees WHERE department_id = dept_id);
END $
DELIMITER;
# 使用
SELECT select_count_by_dept(50);
觸發器:TRIGGER
相當于事件監聽器,當數據庫發生特定事件時,觸發器被觸發,完成相應的處理
-
創建
代碼格式:
CREATE TRIGGER 觸發器名稱
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
BEGIN
代碼塊;
END;
① 案例一:向一張表中添加數據之前,同時向另一張表添加數據
DELIMITER // CREATE TRIGGER test_before_trigger BEFORE INSERT ON table1 FOR EACH ROW BEGININSERT INTO table2(name)VALUES ('before_name...'); END // DELIMITER; # 測試 INSERT INTO table1(age) VALUES(18);
② 案例二:在向employees表中添加員工信息之前,檢驗此員工的工資是否大于領導的工資,大于的話報錯,否則添加成功(
NEW
代表添加的數據信息,OLD
代表刪除的數據信息)DELIMITER // CREATE TRIGGER verify_trigger BEFORE INSERT ON employees FOR EACH ROW BEGINDECLARE manager_sal DECIMAL DEFAULT 0.0;SELECT salary INTO manager_sal FROM employees WHERE employee_id = NEW.manager_id;IF NEW.salary > manager_sal# 拋出錯誤THEN SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = '添加失敗:薪資高于領導工資';END IF; END // DELIMITER;
-
查看
① 查看數據庫中的所有觸發器:SHOW TRIGGERS;
② 查看某個觸發器的定義:SHOW CREATE TRIGGER 觸發器名稱;
-
刪除:
DROP TRAGGER 觸發器名稱;
變量
- 系統變量:以@@開頭
① 查看全局系統變量:SHOW GLOBAL VARIABLES;
② 查看會話系統變量
③ 查看指定系統變量SHOW SESSION VARIABLES; SHOW VARIABLES;
④ 修改系統變量的值SELECT @@global.max_connections; # 查看服務器最大連接數 SELECT @@global.character_set_client; # 查看字符集 SELECT @@session.character_set_client; # 查看字符集 SELECT @@session.pseudo_thread_id; # 查看當前會話的MySQL連接ID SELECT @@character_set_client; # 先查看會話的字符集,若沒有再查看全局的字符集
SET @@global.max_connections = 166; # 修改全局變量,方式一 SET GLOBAL max_connection = 167; # 修改全局變量,方式二SET @@session.character_set_client = 'gbk'; # 修改會話變量,方式一 SET SESSION character_set_client = 'gbk'; # 修改會話變量,方式二
- 用戶變量
① 會話用戶變量:以@開頭
② 局部變量# 聲明和初始化 SET @a = 1; SET @b := 2; SELECT @avg_sal := AVG(salary) FROM employees; # 這種情況必須用:= SELECT COUNT(*) INTO @emp_total FROM employees; #使用 SELECT @a, @b, @avg_sal, @emp_total;
說明:
a、使用關鍵字:DECLARE
b、只能在存儲過程和存儲函數中使用
c、必須寫在BEGIN...END
的首行
d、格式:DECLARE 變量名 類型 [DEFAULT 值]
,若不指明DEFAULT
,則默認是NULL
DELIMITER $ CREATE PROCEDURE test() BEGIN# 聲明局部變量DECLARE a INT DEFAULT 0;DECLARE b INT;DECLARE name VARCHAR(30);#賦值SET a = 5;SET b := 6;SELECT last_name INTO nameFROM employeesWHERE employee_id = 100;#使用SELECT a, b, name; END $ DELIMITER;
定義條件與處理程序
- 定義條件
① 格式:DECLARE 錯誤名稱 CONDITION FOR 錯誤碼;
② 目的:給錯誤碼命名
③ 錯誤碼分類:MySQL_error_code、sqlstate_value - 定義處理程序
① 格式:DECLARE 處理方式 HANDLER FOR 錯誤類型 處理語句;
② 處理方式分類:
a、CONTINUE
:遇到錯誤不處理,繼續執行
b、EXIT
:遇到錯誤馬上退出
c、UNDO
:遇到錯誤后撤回之前的操作
③ 錯誤類型分類
a、SQLSTATE '字符串錯誤碼'
:字符串類型錯誤碼,長度為5
b、MySQL_error_code
:數值類型錯誤碼
c、錯誤名稱:定義條件時聲明的名稱
d、SQLWARNING
:匹配所有以01開頭的錯誤碼
e、NOT FOUND
:匹配所有以02開頭的錯誤碼
f、SQLEXCEPTION
:匹配沒有被d、e匹配到的錯誤碼 - 案例
DELIMITER $ CREATE PROCEDURE UpdateTest() BEGIN# 因email是NOT NULL,所以執行第一個UPDATE會報錯“1048 - Column 'email' cannot be null”# 在此聲明錯誤處理DECLARE CONTINUE HANDLER FOR 1048 SET @message = 'aaa';SET @a = 1;UPDATE employees SET email = NULL WHERE employee_id = 100;SET @a = 2;UPDATE employees SET email = '123@qq.com' WHERE employee_id = 100;SET @a = 3; END $ DELIMITER;# 調用 CALL UpdateTest(); # 查看變量 SELECT @a, @message; // 3, aaa
流程控制
分支結構
-
IF
DELIMITER // CREATE PROCEDURE testIf() BEGINDECLARE score DECIMAL(10,2) DEFAULT 85;IF score >= 90 THEN SELECT 'A';ELSEIF score >= 80 AND score < 90 THEN SELECT 'B';ELSEIF score >= 60 AND score < 80 THEN SELECT 'C';ELSE SELECT 'D';END IF; END // DELIMITER;CALL testIf();
-
CASE
①CASE ... WHEN ... THEN ... WHEN ... THEN ... ELSE ... END CASE;
DELIMITER // CREATE PROCEDURE testCase() BEGINDECLARE n INT DEFAULT 2;CASE nWHEN 1 THEN SELECT 'n = 1';WHEN 2 THEN SELECT 'n = 2';ELSE SELECT 'n = 9';END CASE; END // DELIMITER;
②
CASE WHEN ... THEN ... WHEN ... THEN ... ELSE ... END CASE;
DELIMITER // CREATE PROCEDURE testCase() BEGINDECLARE n INT default 10;CASEWHEN n > 20 THEN SELECT 'n > 20';WHEN n >= 10 THEN SELECT 'n >= 10';ELSE SELECT 'n < 10';END CASE; END // DELIMITER;
循環結構
-
LOOP
DELIMITER // CREATE PROCEDURE testLoop() BEGINDECLARE n INT DEFAULT 1; # n = 1# 開始循環aaa: LOOPIF n >= 8THEN LEAVE aaa;END IF;SET n = n + 1;END LOOP aaa;SELECT n; END // DELIMITER;
-
WHILE
DELIMITER // CREATE PROCEDURE testWhile() BEGINDECLARE n INT DEFAULT 1;WHILE n < 10DOSET n = n + 1;END WHILE;SELECT n; END // DELIMITER;
-
REPEAT
DELIMITER // CREATE PROCEDURE testRepeat() BEGINDECLARE n INT DEFAULT 1;REPEATSET n = n + 1;UNTIL n > 10END REPEAT;SELECT n; END // DELIMITER;
跳轉語句
-
LEAVE
① 同BREAK
,格式:LEAVE 循環名;
② 使用場景:循環體中、BEGIN...END
中DELIMITER // CREATE PROCEDURE testLeave(IN num INT) label_test: BEGINIF num = 0 THEN LEAVE label_test;ELSEIF num < 5 THEN SELECT num;ELSE SELECT 'num >= 5';END IF;SELECT 'is end'; END // DELIMITER;
-
ITERATE
① 同CONTINUE
,格式:ITERATE 循環名;
② 使用場景:循環體中DELIMITER // CREATE PROCEDURE test_iterate() BEGINDECLARE num INT DEFAULT 0;iterate_test: LOOPSET num = num + 1;IF num > 5 THEN LEAVE iterate_test;ELSEIF num > 2 THEN ITERATE iterate_test;ELSE SELECT 'is end';END IF;END LOOP;SELECT num; END // DELIMITER;
游標
隨意的定位到某一條記錄,可以逐條讀取數據。在使用游標過程中,會對數據加鎖,不適合高并發場景。
DELIMITER //
CREATE PROCEDURE test_cursor(IN limit_total_salary DECIMAL, OUT total_count INT)
BEGIN# 聲明變量DECLARE sum_sal DECIMAL DEFAULT 0.0;DECLARE emp_count INT DEFAULT 0;DECLARE emp_sal DECIMAL;# 聲明游標DECLARE cursor_test CURSOR FOR SELECT salary FROM employees ORDER BY salary DESC;# 打開游標OPEN cursor_test;# 使用游標WHILE sum_sal < limit_total_salaryDOFETCH cursor_test INTO emp_sal;SET sum_sal = sum_sal + emp_sal;SET emp_count = emp_count + 1;END WHILE;SET total_count = emp_count;# 關閉游標CLOSE cursor_test;
END //
DELIMITER;
# 調用
CALL test_cursor(100000, @count);
SELECT @count;