一 . 視圖java
視圖,實際上是一個虛擬的表,是跑到內存中的表,可是在表中刪除數據的時候,內存裏面就沒了這些數據。爲何要使用視圖:使用視圖咱們能夠把查詢過程當中臨時表炸出來,保存下來,用視圖去實現,這樣之後再想操做該臨時表的數據就不用寫複雜的sql了,直接去視圖中查找就行。python
select * from course;mysql
select * from teacher;linux
select cname from course where teacher_id = (select tid from teacher where tname='李平老師'); # 子查詢的方式程序員
#子查詢出臨時表,做爲 teacher_id 等判斷依據web
select tid from teacher where tname='李平老師'算法
建立視圖:sql
語法是 create view 視圖名稱 as sql 語句數據庫
create view teacher_view as select tid from teacher where tname='李平老師'; # 建立視圖網絡
show tables; # 查看庫中的表格名
desc teacher_view; # 有表結構
select * from teacher_view; # 有表數據
# 因而查詢李平老師教授的課程名的sql能夠改寫成
select cname from course where teacher_id = (select tid from teacher_view);
刪除:drop view teacher_view
二 . 觸發器 !!!注意觸發器的全部內容都是不空格和不空行的,不然會報錯
create table cmd(內容數據); # 這是一張指令信息表,你在系統裏面執行的任何的系統命令都在表裏
create table errlg(內容數據); # 指令執行錯誤的信息統計表,專門提取上面cmd表的錯誤記錄
#建立觸發器:
delimiter // 或者$$ 均可以
create trigger tri_after_insert_cmd after 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// # 前面打;都不會運行的,只有碰到//這個完成的sql 纔算結束
delimiter; # 而後將mysql的結束符改回爲分號
特別的:new表示即將插入的數據行,old表示即將刪除的數據行。
drop trigger tri_after_insert_cmd;
三 . 事務
簡單來講,事物用於將某些操做的多個sql做爲原子性操做,也就是這些sql語句要麼同時成功,要麼都不成功,一旦有某一個出現錯誤,就會返回來的狀態。
create table user( id int primary key auto_increment, name char(32), balance int ); insert into user(name,balance) values ('wsb',1000), ('chao',1000), ('ysb',1000);
#原子操做 start transaction; update user set balance=900 where name='wsb'; #買支付100元 update user set balance=1010 where name='chao'; #中介拿走10元 update user set balance=1090 where name='ysb'; #賣家拿到90元 commit; #只要不進行commit操做,就沒有保存下來,沒有刷到硬盤上 #出現異常,回滾到初始狀態 start transaction; update user set balance=900 where name='wsb'; #買支付100元 update user set balance=1010 where name='chao'; #中介拿走10元 uppdate user set balance=1090 where name='ysb'; #賣家拿到90元,出現異常沒有拿到 rollback; #若是上面三個sql語句出現了異常,就直接rollback,數據就直接回到原來的狀態了。可是執行了commit以後,rollback這個操做就無法回滾了
#咱們要作的是檢測這幾個sql語句是否異常,沒有異常直接commit,有異常就rollback,可是如今單純的只是開啓了事務,可是尚未說如何檢測異常,咱們先來一個存儲過程來捕獲異常,等咱們學了存儲過程,再細說存儲過程。 commit;
delimiter //
create PROCEDURE p5()
BEGIN
DECLARE exit handler for sqlexception
BEGIN
rollback;
END;
START TRANSACTION;
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='chao'; #中介拿走10元
#update user2 set balance=1090 where name='ysb'; #賣家拿到90元
update user set balance=1090 where name='ysb'; #賣家拿到90元
COMMIT;
END //
delimiter ;
mysql> select * from user;
+----+------+---------+
| id | name | balance | +----+------+---------+ | 1 | wsb | 1000 | | 2 | chao | 1000 | | 3 | ysb | 1000 | +----+------+---------+ 3 rows in set (0.00 sec)
四.存儲過程
存儲過程包含了一系列可執行的sql 語句,存儲過程存放在mysql中,經過調用它的名字能夠執行其內部的一堆sql,
存儲過程的優勢:1.用於替代程序寫sql語句,實現程序與sql解耦
2.基於網絡傳輸,傳別名的數據量小,而直接傳sql數據量大
存儲過程的缺點:程序員擴展功能不方便
存儲過程的三種方法:
#方式一: MySQL:存儲過程 程序:調用存儲過程 #方式二: MySQL: 程序:純SQL語句 #方式三: MySQL: 程序:類和對象,即ORM(本質仍是純SQL語句)
建立存儲過程(有參)
對於存儲過程能夠接受的參數有:in 僅用於傳入參數用 out 僅用於返回值用 inout 既能夠傳入又能夠看成返回值。
存儲過程結合事務來寫 :
delimiter // create procedure p4( out status int ) BEGIN 1. 聲明若是出現異常則執行{ set status = 1; rollback; } 開始事務 -- 由秦兵帳戶減去100 -- 方少偉帳戶加90 -- 張根帳戶加10 commit; 結束 set status = 2; END // delimiter ; #實現 delimiter // create PROCEDURE p5( OUT p_return_code tinyint ) BEGIN DECLARE exit handler for sqlexception #聲明若是一旦出現異常則執行下面的這個begin和end裏面的操做 BEGIN -- ERROR #--是什麼啊,忘了吧,是註釋的意思,就告訴你後面是對錯誤的處理 set p_return_code = 1; #將out返回值改成1了,這是你本身規定的,1表示出錯了 rollback; #回滾事務 END; DECLARE exit handler for sqlwarning #聲明瞭出現警告信息以後你的操做行爲 BEGIN -- WARNING set p_return_code = 2; rollback; END; START TRANSACTION; #其實我們這個存儲過程裏面就是執行這個事務,而且一直檢測着這個事務,一旦出錯或者出現警告,就rollback DELETE from tb1; #事務裏面的任何一條sql執行失敗或者執行出現警告,都會執行上面咱們聲明的那些對應的操做,若是沒有任何的異常,就會自動執行下面的commit,並執行後面成功的sql insert into blog(name,sub_time) values('yyy',now()); #拿個人代碼進行測試的時候,別忘了改爲你本身庫裏的表,還有表裏面對應的字段名要有的,本身測試的時候,能夠本身寫一個錯誤的sql來試試看 COMMIT; -- SUCCESS set p_return_code = 0; #0表明執行成功 END // delimiter ;
執行存儲過程:
-- 無參數
call proc_name()
-- 有參數,全in
call proc_name(1,2)
-- 有參數,有in,out,inout
set @t1=0;
set @t2=3;
call proc_name(1,2,@t1,@t2)
執行存儲過程
在python中基於pymysql來執行存儲過程:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執行存儲過程
cursor.callproc('p1', args=(1, 22, 3, 4))
# 獲取執行完存儲的參數
cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
result = cursor.fetchall()
#conn.commit()
cursor.close()
conn.close()
print(result)
刪除存儲過程:drop procedure proc_name;
五 . 函數
1、數學函數
ROUND(x,y)
返回參數x的四捨五入的有y位小數的值
RAND()
返回0到1內的隨機值,能夠經過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。
2、聚合函數(經常使用於GROUP BY從句的SELECT查詢中)
AVG(col)返回指定列的平均值
COUNT(col)返回指定列中非NULL值的個數
MIN(col)返回指定列的最小值
MAX(col)返回指定列的最大值
SUM(col)返回指定列的全部值之和
GROUP_CONCAT(col) 返回由屬於一組的列值鏈接組合而成的結果
3、字符串函數
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'
4、日期和時間函數
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'
5、加密函數
MD5()
計算字符串str的MD5校驗和
PASSWORD(str)
返回字符串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不一樣的算法。
6、控制流函數
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、控制流函數小練習
#7.一、準備表,將下面這些內容保存爲一個.txt文件或者.sql,而後經過navicat的運行sql文件的功能導入到數據庫中,還記得嗎?
/*
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', 'chao');
INSERT INTO `teacher` VALUES ('4', 'peiqi');
#7.二、統計各科各分數段人數.顯示格式:課程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;
# 須要掌握的函數:date_format :
# 函數中不要寫sql語句(不然會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能
刪除函數:
drop function func_name;
執行函數:
# 獲取返回值
select upper('gongfu') into @res;
select @res;
# 在查詢中使用
select f1(11,nid),name from tb2;