目录
一,函数
–1,工具的使用
1,找到.exe程序,双击,输入了密码,点击连接,就可以了
2,创建库: 右键-新建数据库-设置数据库名-选字符集utf8-确定
3,创建表: 右键-创建表-输入字段名字段类型字段长度字段约束-创建表-输入表名-确定
4,添加表里的记录,如下图:
–2,准备数据
CREATE TABLE dept(
deptno int primary key auto_increment ,
dname VARCHAR(20),
loc VARCHAR(13)
);
INSERT INTO dept VALUES(null,'accounting','一区');
INSERT INTO dept VALUES(null,'research','二区');
INSERT INTO dept VALUES(null,'operations','二区');
CREATE TABLE emp(
empno int primary key auto_increment,
ename VARCHAR(10),
job VARCHAR(10),
mgr int,
hiredate DATE,
sal double,
comm NUMERIC(7,2),
deptno int
);
INSERT INTO emp VALUES(100,'jack','副总',NULL,'2002-05-1',90000,NULL,1);
INSERT INTO emp VALUES(200,'tony','总监',100,'2015-02-02',10000,2000,2);
INSERT INTO emp VALUES(300,'hana','经理',200,'2017-02-02',8000,1000,2);
INSERT INTO emp VALUES(400,'leo','员工',300,'2019-02-22',3000,200.12,2);
INSERT INTO emp VALUES(500,'liu','员工',300,'2019-03-19',3500,200.58,2);
–3,基础函数的使用
lower–全转小写
upper–全转大写
length–求长度
substr–截取子串
concat–拼接字符串
replace–替换
#SQL中的函数
#SELECT 列名1,列名2 FROM 表名
SELECT * FROM emp #查询所有列
SELECT ename FROM emp #查名字
SELECT empno,ename FROM emp #查编号和名字
SELECT empno a FROM emp #给列设置别名
#UPPER转大写 列名 列的别名
SELECT ename,UPPER(ename) a FROM emp
#lower转小写 列名
SELECT ename,LOWER(ename) FROM emp
#length求长度,根据u8,一个字母或数字长度为1,一个汉字长度为3
SELECT ename,LENGTH(ename) FROM emp#查ename的长度
SELECT ename,job,LENGTH(job) FROM emp#查job的长度
#substr截取子串
#SUBSTR(a,b)-a是截取谁b是从哪个字符开始
SELECT ename,SUBSTR(ename,2) FROM emp
#SUBSTR(a,b,c)-a是截取谁b是从哪个字符开始c是截取的长度
SELECT ename,SUBSTR(ename,2,2) FROM emp
#concat(a,b,...)拼串-a是列名b是要拼接的数据
#...是指可以有多个参数
SELECT ename,CONCAT(ename,"hello",1,2) FROM emp
#替换replace(a,b,c)-a是字段名把b换成c
SELECT ename,REPLACE(ename,'a','666') FROM emp
#ifnull(a,b)-a是字段名b是要换成的值
SELECT comm,IFNULL(comm,100) FROM emp#如果是null就换成100
#查询每个员工的月薪
SELECT sal,comm,sal+IFNULL(comm,0) FROM emp
#对小数的函数:
SELECT comm,ROUND(comm) FROM emp#四舍五入,取整
SELECT comm,ROUND(comm,1) FROM emp#四舍五入,保留1位小数
SELECT comm,CEIL(comm) FROM emp#ceil向上取整
SELECT comm,FLOOR(comm) FROM emp#floor向下取整
#对日期数据的函数:
SELECT NOW() #当前时间
SELECT YEAR('1999-1-1')
SELECT YEAR( NOW() )#当前年
SELECT MONTH( NOW() ),DAY( NOW() )#当前月,当前日
#hour时 minute分 second秒
SELECT HOUR( NOW() ),MINUTE( NOW() ),SECOND( NOW() )
#生成一个32位的随机数
SELECT UUID()
#\表示转义符号,把'当做普通的字符在使用而不是字符串的标记
SELECT 'xi\'an'
round & ceil & floor
round四舍五入,ceil向上取整,floor向下取整
–直接四舍五入取整
select comm,round(comm) from emp
–四舍五入并保留一位小数
select comm,round(comm,1) from emp
–ceil向上取整,floor向下取整
select comm,ceil(comm) ,floor(comm) from emp
uuid
SELECT UUID()
返回uuid:a08528ca-741c-11ea-a9a1-005056c00001
now
select now() -- 年与日 时分秒
select curdate() --年与日
select curtime() --时分秒
year & month & day
–hour()时 minute()分 second()秒
select now(),hour(now()),minute(now()),second(now()) from emp ;
–year()年 month()月 day()日
select now(),year(now()),month(now()),day(now()) from emp ;
转义字符
'作为sql语句符号,内容中出现单撇就会乱套,进行转义即可
select 'ab'cd' -- 单引号是一个SQL语句的特殊字符
select 'ab\'cd' --数据中有单引号时,用一个\转义变成普通字符
二,MySQL数据的备份
–1,用工具直接备份就行
1,如果是SQL,直接ctrl s保存就行
2,也可以把表或者数据库一整个导出–右键–导出–以SQL转储文件…
三,条件查询
–1,基础语法
#条件查询
#1.去重distinct
SELECT DISTINCT loc FROM dept #查询部门地址
#2.where连接查询的条件
#select 字段名 from 表名 where 字段名=字段值
#练习1:查询编号为1的部门信息
SELECT * FROM dept WHERE deptno=1
#练习2:查询编号>1的部门信息
SELECT * FROM dept WHERE deptno>1
SELECT * FROM dept WHERE deptno<2
SELECT * FROM dept WHERE deptno!=1
SELECT * FROM dept WHERE deptno<>1 #表示!=,同上
#练习3:查询名称是research的部门编号
SELECT deptno FROM dept WHERE dname='research'
#练习4:查询地址在二区编号为3的部门名称
SELECT dname FROM dept WHERE
loc='二区' AND deptno=3 #并且关系
#练习5:查询部门名称是accounting/research的部门地址
SELECT loc FROM dept WHERE
#dname='accounting' or dname='research'#或者关系
dname IN('accounting','research')#in子句in(a,b),同上
#练习6:查询编号是1 2 3的部门信息
SELECT * FROM dept WHERE
deptno IN(1,2,3)
#3.like--模糊查询,%通配符0~n个字符,_通配符1个字符
#练习1:查询名字包含a的员工信息
SELECT * FROM emp WHERE
ename LIKE '%a%' #包含a
#ename LIKE 'a_' #a后只有一个,了解
②练习
#练习SQL语句:
#练习1:查询部门地址在二区的部门名称
SELECT dname FROM dept WHERE loc='二区'
#练习2:查询部门地址在二区名字里有o的部门编号
SELECT deptno FROM dept WHERE
loc='二区' AND dname LIKE '%o%'
#练习3:查询名字以l开头的员工岗位并去重
SELECT DISTINCT job FROM emp WHERE ename LIKE 'l%'
#练习4:查询15年到19年入职的员工姓名和岗位
SELECT ename,job FROM emp WHERE
#year(hiredate)>=2015 and YEAR(hiredate)<=2019
hiredate>='2015-1-1' AND hiredate<='2019-12-31'
#练习5:查询副总的年薪
SELECT sal*12+IFNULL(comm,0)*12 FROM emp WHERE job='副总'
–2,null(查询是否为空)
#1.null的数据用is /is not关键字来过滤
#练习1:查询没有奖金的员工信息
SELECT * FROM emp WHERE comm IS NULL
#练习2:查询有奖金的员工信息
SELECT * FROM emp WHERE comm IS NOT NULL
–3,between and(查询条件范围)
#练习3:查询工资5000~10000的员工信息
SELECT * FROM emp WHERE
#sal>=5000 and sal<10000
sal BETWEEN 5000 AND 10000 #[5000,10000]
#练习4:查询2019年入职的员工姓名
SELECT ename FROM emp WHERE
#hiredate between '2019-1-1' and '2019-12-31'
YEAR(hiredate)=2019
–4,limit(分页)
#练习5:展示前两条员工数据
SELECT * FROM emp LIMIT 2 #只取前n条
SELECT * FROM emp LIMIT 0,2 #从0+1的数据开始,总共展示2条
#练习6:查询岗位是员工的第一条记录
SELECT * FROM emp WHERE job='员工' LIMIT 0,1#limit通常放最后
–5,order by(升降排序)
#4.order by排序,按照字典顺序排,默认是升序ASC
#练习7:按照工资排序
SELECT * FROM emp ORDER BY sal DESC #按数值降序
#练习8:按照名字排序
SELECT * FROM emp ORDER BY ename DESC #按字母降序
#练习9:按照岗位排序
SELECT * FROM emp ORDER BY job ASC #按汉字对应的编号升序
#练习10:查询15年到19年入职的员工信息只取前两条并按照工资升序排
SELECT * FROM emp WHERE
YEAR(hiredate) BETWEEN 2015 AND 2019 #区间[2015,2019]
ORDER BY sal #排序,默认的升序
LIMIT 2 #分页,只取前两条,通常放最后
–6,like(模糊查询)
通配符%代表0到n个字符,通配符下划线_代表1个字符
select * from emp where ename like 'l%' --以l开头的
select * from emp where ename like '%a' --以a结束的
select * from emp where ename like '%a%' --中间包含a的
select * from emp where ename like 'l__' --l后面有两个字符的 _代表一个字符位置
–7,where(条件查询)
注意:where中不能使用列别名!!
select * from emp
select * from emp where 1=1 --类似没条件
select * from emp where 1=0 --条件不成立
select * from emp where empno=100 --唯一条件
select * from emp where ename='tony' and deptno=2 --相当于两个条件的&关系
select * from emp where ename='tony' or deptno=1 --相当于两个条件的|关系
select name, sal from emp where sal=1400 or sal=1600 or sal=1800;
-- 或
select name, sal from emp where sal in(1400,1600,1800);
select name, sal from emp where sal not in(1400,1600,1800);
–8,distinct(去重)
使用distinct关键字,去除重复的记录行
SELECT loc FROM dept;
SELECT DISTINCT loc FROM dept;
–9,统计案例
#统计需求
#练习1:统计每个员工的年薪
SELECT sal,comm,sal*16+IFNULL(comm,0)*16 FROM emp
#练习2:统计19年以前入职的员工信息
SELECT * FROM emp WHERE
YEAR(hiredate)<2019
三,聚合函数
–1,概述
基础函数:
upper lower length concat substr replace ifnull now()/date()/year()…
聚合函数:
把一个字段的值聚合起来,进行获取最大值,最小值,平均数,求和,求个数…
max() min() sum() avg() count()
–2,测试
#聚合函数max min sum avg count
#最大值 最小值 求和 求平均数
SELECT MAX(sal),MIN(sal),SUM(sal),AVG(sal) FROM emp
#求总记录数
SELECT COUNT(*) FROM emp#低效
SELECT COUNT(1) FROM emp#高效
SELECT COUNT(sal) FROM emp#了解,不推荐
SELECT COUNT(comm) FROM emp#按照字段统计时不统计null
#练习1:统计名字里包含a的总记录数
SELECT COUNT(1) FROM emp WHERE ename LIKE '%a%'
#练习2:统计19年入职的员工里的最高薪
SELECT MAX(sal) FROM emp WHERE YEAR(hiredate)=2019
#练习3:统计2号部门的平均薪资
SELECT AVG(sal) FROM emp WHERE deptno=2
#练习4:统计2号部门一年的工资支出总数
SELECT SUM(sal)*12 FROM emp WHERE deptno=2
四,分组
把表里的所有数据 按照 合理的维度 分成不同的组
–1,group by(分组)
#分组:使用group by
#练习1:统计每个部门的平均薪资
SELECT AVG(sal),deptno FROM emp
GROUP BY deptno #按照部门分组
#练习2:统计每个部门的最高薪资
SELECT MAX(sal),deptno FROM emp
#口诀1:查询结果中出现了混合列,包括着聚合列和非聚合列,必须分组
GROUP BY deptno
#口诀2:通常按照非聚合列分组
#练习3:统计每年入职的总人数
SELECT YEAR(hiredate),COUNT(1) FROM emp
GROUP BY YEAR(hiredate)
#练习4:统计每个岗位的平均薪资
SELECT AVG(sal),job FROM emp
GROUP BY job
–2,having(分组条件查询)
把分组后的数据还想继续过滤,使用group by的固定搭配having
#having
#练习5:统计每个岗位的平均薪资,而且只要>=10000的
SELECT AVG(sal) a,job FROM emp
#where AVG(sal)>=10000
#注意:::where里不能用别名,也不能出现聚合函数
GROUP BY job #按照非聚合列分组
HAVING a>=10000 #分组后的过滤,a是别名
#练习6:统计每年入职的人数,而且只要19年的
SELECT YEAR(hiredate) ,COUNT(1) FROM emp
WHERE YEAR(hiredate)=2019
GROUP BY YEAR(hiredate) #分组
#having a=2019 #分组后的过滤
# where比having 高效,因为执行时机要早一些
五,事务(要么全成功,要么全失败)
–1,概述
1,数据库事务用来保证 多个SQL 要么全成功,要么全失败.英文叫transaction.
MySQL数据库会自动管理事务,Oracle数据库需要程序员管理事务.
MySQL也允许程序员手动管理事务
2,事务的四大特征:ACID
原子性: 把多条SQL看做一个原子密不可分,要么全成功,要么全失败
一致性: 保证数据守恒,将来广泛的应用到分布式系统里
隔离性: MySQL数据库可以支持高并发,可能会有数据安全的隐患,也有复杂的隔离级别
持久性: 对数据库的操作增删改,有持久影响
3,隔离级别:
read uncommitted读未提交:性能好,但是安全性差
read commited读已提交:是Oracle数据库默认的隔离级别,性能较差,但是安全性较好
repeatable read可重复读:是MySQL数据库默认的隔离级别,性能再差一点,但是安全性特别好
Serializable串行化:性能非常差,但是安全性比较好
也可以查:SELECT @@tx_isolation;
–2,测试
提交 commit
#多条语句时,批量执行,事务提交
#有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱
#mysql的事务默认就是开启的 -- 多条语句一起操作时,要么一起成功要么一起失败
窗口1:
mysql> use cgb210901; #使用数据库,准备往表里插入数据
mysql> start transaction; #开启事务start transaction
mysql> insert into g values(null,'jack',20);#多条执行增删改的SQL
mysql> commit;#提交事务commit,不提交的话别人查不到的,没有持久影响
窗口2:
mysql> use cgb210901;
mysql> select * from g; #窗口1不执行commit,这里永远查不到的
回滚 rollback
#多条语句,批量执行,insert插入重复的主键导致失败时,事务回滚
BEGIN;
INSERT INTO user (id) VALUES(15);
INSERT INTO user (id) VALUES(35);#存在了
ROLLBACK;#事务回滚,就不会再提交了
–3,SQL练习
–1,测试
#练习1:依次按照多个条件排序,asc升序,desc降序
SELECT * FROM emp ORDER BY sal DESC,ename ASC
SELECT * FROM emp ORDER BY deptno DESC,ename ASC
#练习2:统计每个岗位的员工人数
SELECT job,COUNT(1) FROM emp
#什么时候必须需要分组?查询时出现了混合列
#按照啥分组?按照非聚合列分组
GROUP BY job
#练习3:统计每个部门包含re的部门编号
SELECT deptno FROM dept
WHERE dname LIKE 're%' #以re开始的
GROUP BY loc #合理的分组
#练习4:统计每年入职的员工的最高薪资,只要>5000的
SELECT MAX(sal) a,YEAR(hiredate) b FROM emp
GROUP BY b #分组,除了where里不能用别名其他位置都行
#having里可用聚合函数where不能
HAVING a>5000 #分组后过滤
#练习5:查询所有员工的最高薪-用分页
SELECT MAX(sal) FROM emp
SELECT sal FROM emp ORDER BY sal DESC LIMIT 1
#创建user表(id,name,pwd),并插入数据
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,#主键自增
NAME VARCHAR(20),
pwd VARCHAR(10)
)
INSERT INTO USER VALUES(NULL,'jack',"123")
INSERT INTO USER VALUES(NULL,'rose',"456")
#对上面SQL中使用的事务进行优化,因为上面的SQL需要两个事务的开启和关闭
#下面这种SQL也叫作批量插入的功能,高效,多次插入使用同一个事务
INSERT INTO USER VALUES
(NULL,'tony',"123"),(NULL,'jerry',"456")