一、視圖
視圖是一個虛擬表(非真實存在),其本質是【根據SQL陳述句獲取動態的資料集,并為其命名】,用戶使用時只需使用【名稱】即可獲取結果集,可以將該結果集當做表來使用;
使用視圖我們可以把查詢程序中的臨時表摘出來,用視圖去實作,這樣以后再想操作該臨時表的資料時就無需重寫復雜的sql了,直接去視圖中查找即可,但視圖有明顯地效率問題,并且視圖是存放在資料庫中的,如果我們程式中使用的sql過分依賴資料庫中的視圖,即強耦合,那就意味著擴展sql極為不便,因此并不推薦使用,
ps: 視圖在庫里只有表結構檔案沒有表資料
我們不應該修改視圖中的記錄,而且在涉及多個表的情況下是根本無法修改視圖中的記錄的
# =============================創建視圖 select * from emp inner join dep on emp.dep_id = dep.id; create view emp2dep as select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id; mysql> update emp2dep set name="EGON" where id=1; Query OK, 1 row affected (0.05 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from emp2dep; +----+-----------+--------+------+--------+--------------+ | id | name | sex | age | dep_id | dep_name | +----+-----------+--------+------+--------+--------------+ | 1 | EGON | male | 18 | 200 | 技術 | | 2 | alex | female | 48 | 201 | 人力資源 | | 3 | wupeiqi | male | 38 | 201 | 人力資源 | | 4 | yuanhao | female | 28 | 202 | 銷售 | | 5 | liwenzhou | male | 18 | 200 | 技術 | +----+-----------+--------+------+--------+--------------+ 5 rows in set (0.00 sec) mysql> mysql> mysql> select * from emp; +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 1 | EGON | male | 18 | 200 | | 2 | alex | female | 48 | 201 | | 3 | wupeiqi | male | 38 | 201 | | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | | 7 | lili | female | 48 | NULL | +----+------------+--------+------+--------+ 7 rows in set (0.00 sec) mysql> # =============================修改視圖 alter view emp2dep as 查詢陳述句; # =============================洗掉視圖 drop view emp2dep;
二、觸發器
使用觸發器可以定制用戶對表進行【增、刪、改】操作時前后的行為,注意:沒有查詢
特別的:NEW表示即將插入的資料行,OLD表示即將洗掉的資料行
觸發器無法由用戶直接呼叫,而知由于對表的【增/刪/改】操作被動引發的,
# 增=》insert create trigger tri_before_insert_t1 before insert on t1 for each row begin sql陳述句; end create trigger tri_after_insert_t1 after insert on t1 for each row begin sql陳述句; end # 洗掉=》delete create trigger tri_before_delete_t1 before delete on t1 for each row begin sql陳述句; end create trigger tri_after_delete_t1 after delete on t1 for each row begin sql陳述句; end # 修改=》update # 例如 insert into tt1 values(1,"egon",'male'); delimiter // create trigger tri_before_insert_tt1 before insert on tt1 for each row begin insert into tt2 values(NEW.name); end // delimiter ; insert into tt1 values(2,"tom",'female'); # 練習 CREATE TABLE cmd ( id INT PRIMARY KEY auto_increment, USER CHAR (32), priv CHAR (10), cmd CHAR (64), sub_time datetime, #提交時間 success enum ('yes', 'no') #0代表執行失敗 ); CREATE TABLE errlog ( id INT PRIMARY KEY auto_increment, err_cmd CHAR (64), err_time datetime ); delimiter $$ create trigger tri_after_insert_cmd after insert on cmd for each row begin if NEW.success = 'no' then insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time); end if; end $$ delimiter ; insert into cmd(user,priv,cmd,sub_time,success) values ('egon','0755','ls -l /etc',NOW(),'yes'), ('egon','0755','cat /etc/passwd',NOW(),'no'), ('egon','0755','useradd xxx',NOW(),'no'), ('egon','0755','ps aux',NOW(),'yes'); drop trigger tri_after_insert_cmd ;
三、存盤程序
存盤程序包含了一系列可執行的sql陳述句,存盤程序存放于MySQL中,通過呼叫它的名字可以執行其內部的一堆sql
使用存盤程序的 優點: 1. 用于替代程式寫的SQL陳述句,實作程式與sql解耦 2. 基于網路傳輸,傳別名的資料量小,而直接傳sql資料量大 缺點: 1. 程式員擴展功能不方便
程式與資料庫結合使用的三種方式
#方式一:
MySQL:存盤程序
程式:呼叫存盤程序
#方式二:
MySQL:
程式:純SQL陳述句
#方式三:
MySQL:
程式:類和物件,即ORM(本質還是純SQL陳述句)
對于存盤程序,可以接收引數,其引數有三類: in 僅用于傳入引數用 out 僅用于回傳值用 inout 既可以傳入又可以當作回傳值
# 創建無參存盤程序 delimiter $$ create procedure p1() begin select * from emp; end $$ delimiter ; call p1(); # 創建有參存盤程序 delimiter $$ create procedure p2( in n int, out res int ) begin select * from emp where id > n; set res=1; end $$ delimiter ; ==========================>在mysql里呼叫存盤程序 mysql> set @x=1111; Query OK, 0 rows affected (0.00 sec) mysql> call p2(3,x); ERROR 1414 (42000): OUT or INOUT argument 2 for routine db4.p2 is not a variable or NEW pseudo-variable in BEFORE trigger mysql> call p2(3,@x); +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | | 7 | lili | female | 48 | NULL | +----+------------+--------+------+--------+ 4 rows in set (0.00 sec) Query OK, 0 rows affected (0.01 sec) mysql> select @x; +------+ | @x | +------+ | 1 | +------+ 1 row in set (0.00 sec)
==========================>在pymysql里呼叫存盤程序
import pymysql # pip3 install pymysql conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="123", db="db4", charset="utf8mb4") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.callproc('p2',(3,0)) # @_p2_0=3,@_p2_1=0 ''' set @_p2_0=3 set @_p2_1=0 call p2(@_p2_0,@_p2_1); ''' print(cursor.fetchall()) cursor.execute("select @_p2_1;") print(cursor.fetchall()) cursor.execute("select @_p2_0;") print(cursor.fetchall()) cursor.close() conn.close()
==========================>洗掉存盤程序
drop procedure proc_name;
四、函式
一、數學函式 ROUND(x,y) 回傳引數x的四舍五入的有y位小數的值 RAND() 回傳0到1內的隨機值,可以通過提供一個引數(種子)使RAND()亂數生成器生成一個指定的值, 二、聚合函式(常用于GROUP BY從句的SELECT查詢中) AVG(col)回傳指定列的平均值 COUNT(col)回傳指定列中非NULL值的個數 MIN(col)回傳指定列的最小值 MAX(col)回傳指定列的最大值 SUM(col)回傳指定列的所有值之和 GROUP_CONCAT(col) 回傳由屬于一組的列值連接組合而成的結果 三、字串函式 CHAR_LENGTH(str) 回傳值為字串str 的長度,長度的單位為字符,一個多位元組字符算作一個單字符, CONCAT(str1,str2,...) 字串拼接 如有任何一個引數為NULL ,則回傳值為 NULL, CONCAT_WS(separator,str1,str2,...) 字串拼接(自定義連接符) CONCAT_WS()不會忽略任何空字串, (然而會忽略所有的 NULL), CONV(N,from_base,to_base) 進制轉換 例如: SELECT CONV('a',16,2); 表示將 a 由16進制轉換為2進制字串表示 FORMAT(X,D) 將數字X 的格式寫為'#,###,###.##',以四舍五入的方式保留小數點后 D 位, 并將結果以字串的形式回傳,若 D 為 0, 則回傳結果不帶有小數點,或不含小數部分, 例如: SELECT FORMAT(12332.1,4); 結果為: '12,332.1000' INSERT(str,pos,len,newstr) 在str的指定位置插入字串 pos:要替換位置其實位置 len:替換的長度 newstr:新字串 特別的: 如果pos超過原字串長度,則回傳原字串 如果len超過原字串長度,則由新字串完全替換 INSTR(str,substr) 回傳字串 str 中子字串的第一個出現位置, LEFT(str,len) 回傳字串str 從開始的len位置的子序列字符, LOWER(str) 變小寫 UPPER(str) 變大寫 REVERSE(str) 回傳字串 str ,順序和字符順序相反, SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len) 不帶有len 引數的格式從字串str回傳一個子字串,起始于位置 pos,帶有len引數的格式從字串str回傳一個長度同len字符相同的子字串,起始于位置 pos, 使用 FROM的格式為標準 SQL 語法,也可能對pos使用一個負值,假若這樣,則子字串的位置起始于字串結尾的pos 字符,而不是字串的開頭位置,在以下格式的函式中可以對pos 使用一個負值, mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki' 四、日期和時間函式 CURDATE()或CURRENT_DATE() 回傳當前的日期 CURTIME()或CURRENT_TIME() 回傳當前的時間 DAYOFWEEK(date) 回傳date所代表的一星期中的第幾天(1~7) DAYOFMONTH(date) 回傳date是一個月的第幾天(1~31) DAYOFYEAR(date) 回傳date是一年的第幾天(1~366) DAYNAME(date) 回傳date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) 根據指定的fmt格式,格式化UNIX時間戳ts HOUR(time) 回傳time的小時值(0~23) MINUTE(time) 回傳time的分鐘值(0~59) MONTH(date) 回傳date的月份值(1~12) MONTHNAME(date) 回傳date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() 回傳當前的日期和時間 QUARTER(date) 回傳date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) 回傳日期date為一年中第幾周(0~53) YEAR(date) 回傳日期date的年份(1000~9999) 重點: DATE_FORMAT(date,format) 根據format字串格式化date值 mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', -> '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', -> '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00' 五、加密函式 MD5() 計算字串str的MD5校驗和 PASSWORD(str) 回傳字串str的加密版本,這個加密程序是不可逆轉的,和UNIX密碼加密程序使用不同的演算法, 六、控制流函式 CASE WHEN[test1] THEN [result1]...ELSE [default] END 如果testN是真,則回傳resultN,否則回傳default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 如果test和valN相等,則回傳resultN,否則回傳default IF(test,t,f) 如果test是真,回傳t;否則回傳f IFNULL(arg1,arg2) 如果arg1不是空,回傳arg1,否則回傳arg2 NULLIF(arg1,arg2) 如果arg1=arg2回傳NULL;否則回傳arg1 七、控制流函式小練習 #7.1、準備表 /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50720 Source Host : localhost:3306 Source Database : student Target Server Type : MYSQL Target Server Version : 50720 File Encoding : 65001 Date: 2018-01-02 12:05:30 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `c_id` int(11) NOT NULL, `c_name` varchar(255) DEFAULT NULL, `t_id` int(11) DEFAULT NULL, PRIMARY KEY (`c_id`), KEY `t_id` (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO `course` VALUES ('1', 'python', '1'); INSERT INTO `course` VALUES ('2', 'java', '2'); INSERT INTO `course` VALUES ('3', 'linux', '3'); INSERT INTO `course` VALUES ('4', 'web', '2'); -- ---------------------------- -- Table structure for score -- ---------------------------- DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `s_id` int(10) DEFAULT NULL, `c_id` int(11) DEFAULT NULL, `num` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of score -- ---------------------------- INSERT INTO `score` VALUES ('1', '1', '1', '79'); INSERT INTO `score` VALUES ('2', '1', '2', '78'); INSERT INTO `score` VALUES ('3', '1', '3', '35'); INSERT INTO `score` VALUES ('4', '2', '2', '32'); INSERT INTO `score` VALUES ('5', '3', '1', '66'); INSERT INTO `score` VALUES ('6', '4', '2', '77'); INSERT INTO `score` VALUES ('7', '4', '1', '68'); INSERT INTO `score` VALUES ('8', '5', '1', '66'); INSERT INTO `score` VALUES ('9', '2', '1', '69'); INSERT INTO `score` VALUES ('10', '4', '4', '75'); INSERT INTO `score` VALUES ('11', '5', '4', '66.7'); -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `s_id` varchar(20) NOT NULL, `s_name` varchar(255) DEFAULT NULL, `s_age` int(10) DEFAULT NULL, `s_sex` char(1) DEFAULT NULL, PRIMARY KEY (`s_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('1', '魯班', '12', '男'); INSERT INTO `student` VALUES ('2', '貂蟬', '20', '女'); INSERT INTO `student` VALUES ('3', '劉備', '35', '男'); INSERT INTO `student` VALUES ('4', '關羽', '34', '男'); INSERT INTO `student` VALUES ('5', '張飛', '33', '女'); -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `t_id` int(10) NOT NULL, `t_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of teacher -- ---------------------------- INSERT INTO `teacher` VALUES ('1', '大王'); INSERT INTO `teacher` VALUES ('2', 'alex'); INSERT INTO `teacher` VALUES ('3', 'egon'); INSERT INTO `teacher` VALUES ('4', 'peiqi'); #7.2、統計各科各分數段人數.顯示格式:課程ID,課程名稱,[100-85],[85-70],[70-60],[ <60] select score.c_id, course.c_name, sum(CASE WHEN num BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[100-85]', sum(CASE WHEN num BETWEEN 70 and 85 THEN 1 ELSE 0 END) as '[85-70]', sum(CASE WHEN num BETWEEN 60 and 70 THEN 1 ELSE 0 END) as '[70-60]', sum(CASE WHEN num < 60 THEN 1 ELSE 0 END) as '[ <60]' from score,course where score.c_id=course.c_id GROUP BY score.c_id;MySQL中內置函式
需要掌握函式:date_format
#1 基本使用 mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', -> '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', -> '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00' #2 準備表和記錄 CREATE TABLE blog ( id INT PRIMARY KEY auto_increment, NAME CHAR (32), sub_time datetime ); INSERT INTO blog (NAME, sub_time) VALUES ('第1篇','2015-03-01 11:31:21'), ('第2篇','2015-03-11 16:31:21'), ('第3篇','2016-07-01 10:21:31'), ('第4篇','2016-07-22 09:23:21'), ('第5篇','2016-07-23 10:11:11'), ('第6篇','2016-07-25 11:21:31'), ('第7篇','2017-03-01 15:33:21'), ('第8篇','2017-03-01 17:32:21'), ('第9篇','2017-03-01 18:31:21'); #3. 提取sub_time欄位的值,按照格式后的結果即"年月"來分組 SELECT DATE_FORMAT(sub_time,'%Y-%m'),COUNT(1) FROM blog GROUP BY DATE_FORMAT(sub_time,'%Y-%m'); #結果 +-------------------------------+----------+ | DATE_FORMAT(sub_time,'%Y-%m') | COUNT(1) | +-------------------------------+----------+ | 2015-03 | 2 | | 2016-07 | 4 | | 2017-03 | 3 | +-------------------------------+----------+ 3 rows in set (0.00 sec)
自定義函式
ps:
函式中不要寫sql陳述句(否則會報錯),函式僅僅只是一個功能,是一個在sql中被應用的功能 若要想在begin...end...中寫sql,請用存盤程序
#1 delimiter // create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END // delimiter ; #2 delimiter // create function f5( i int ) returns int begin declare res int default 0; if i = 10 then set res=100; elseif i = 20 then set res=200; elseif i = 30 then set res=300; else set res=400; end if; return res; end // delimiter ;
洗掉函式
drop function func_name;
執行函式
# 獲取回傳值 select UPPER('egon') into @res; SELECT @res; # 在查詢中使用 select f1(11,nid) ,name from tb2;
五、流程控制
條件陳述句
#if條件陳述句 delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT 1; ELSEIF i = 2 THEN SELECT 2; ELSE SELECT 7; END IF; END // delimiter ;
回圈陳述句
#while回圈陳述句 delimiter // CREATE PROCEDURE proc_while () BEGIN DECLARE num INT ; SET num = 0 ; WHILE num < 10 DO SELECT num ; SET num = num + 1 ; END WHILE ; END // delimiter ;
#repeat 回圈 delimiter // CREATE PROCEDURE proc_repeat () BEGIN DECLARE i INT ; SET i = 0 ; repeat select i; set i = i + 1; until i >= 5 end repeat; END // delimiter ;
#loop回圈 BEGIN declare i int default 0; loop_label: loop set i=i+1; if i<8 then iterate loop_label; end if; if i>=10 then leave loop_label; end if; select i; end loop loop_label; END
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/389.html
標籤:Python
