一 . 视图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;