MySQL 5.5 3安装教程:http://www.zhanshaoyi.com/5056.html
数据库
|--DB
//含义:按照一定的数据结构来 存储 数据的 容器。
数据库管理员
|--DBA
|--运维数据库
数据库管理系统
|--DBMS
|--含义:一款软件
// 管理 数据库(DB)
//安全性
//访问
//解析用户的操作
//内置函数
//...
------------------------------------------------------
数据管理过程
|--手工记录
|--文件系统
|--数据库管理系统
|--流程
|--应用1 ---数据库管理
|--应用2 ---系统
|
|
数据库
关系型数据库
|--核心
|--表
|--列和行组成
|--列(表头)
|--字段
|--属性
|--行(数据)
|--记录
|--保存数据的步骤
|--第一步:先确定多少列--->先新建表的结构(定义多少列)
|--第二步:添加数据
名字 访问时间 事由 ...
张三 2019-11-11 xx
张三 2019-11-11 xx
...
SQLSERVER数据库
|--含义:SQLSERVER数据库管理系统
Mysql数据库
|--含义:MySQL关系数据库管理系统(RDBMS),开源免费
|--安装 5.5
//注意
//选择编码方式 utf-8
//是否添加的path
//root root
-------------------------------------------------
SVN地址
|--https://pc-201903161646/svn/17一班/trunk
命令
---------------------------------
|--查看版本 select version();
|--查看数据库(数据库实例) show databases();
//一般一个项目对应一个数据库实例
//包含很多表
|--选择使用具体数据库实例 use 数据库名;
|--列出多有的表 show tables;
|--查看表的结构 desc 表名;
MYSQL体系结构(模块)
存储引擎
|--含义:
不同的存储引擎数据存储的结构是不一样的;
不同的存储引擎特点也不一样。
特点 性能
//MYISAM 强
//INNODB 支持事务/行级锁/外键 低
//对数据库的一组操作要么同时成功失败
查看mysql支持的存储引擎
|--show engines;
|--修改存储引擎
//安装目录下的my.ini
//default-storage-engine=新的存储引擎; //重新启动mysql
字符集
|--编码:
含义:字符和数值之间映射关系
|--字符集
含义:字符和编码的集合
//gbk
//utf-8
//iso8859-1
//gbk2312
//...
|--乱码
含义:编码和解码不一致
mysql字符集(编码方式)
-------------------------------------------
列出所有字符集信息
|--show variables like '%char%'; %:任意
--------------------------------------------------------------------------------
创建数据库
|--create database [if not exists] 数据库名 //[] 可选
删除
|--drop database 数据库名;
查看创建数据库信息
|--show create database 数据库名;
ER图
-----------------
|--含义:实体 的 关系 图
//属性1 类型1
//属性n 类型n
主键
|--用来唯一区别记录的。
|--要求:唯一&&不能为null。
|--注意:千万不要用业务数据作为主键
复合主键
|--用多个列来充当主键
|--注意:
每个列都不能为null
外键
|--含义:某一列的数值是来自其他表的主键
约束
|--含义:限制列要符合某些规则。
|--非空 NOT NULL 比如:idloginNamepassword...看需求
|--唯一 unique 比如:idloginNamephone...
|--主键
|--外键
|--字符串的长度约束
|--精度
|--check //定义的约束条件
User
---------------------
id name loginName password address ...
数据类型
|--性能
|--方便处理数据
MYSQL常用数据类型
|--数值
//整型
//bit [1,64]
//tinyint byte
//bool <==>tinyint(1)
//smallint mediunint int big int
//小数点
//float(m,n) //
//double(m,n) //小数点的精度
//decimal(m,n) //价钱...
|--时间类型
//date 年月日
//time 时分秒
//datetime年月日时间分秒
//year
//timestamp 时间戳
|--字符串
|--char(m) 比如:身份证手机号...
|--varchar(m) 变长
|--text 文本 比如:文章内容
test1
create table department(
dmid int primary key,
dmname varchar(20) unique ,
dmdirector varchar(20) not null,
dmloc char(8) check (dmloc in('南湖校区','浑湖校区') )
);
create table test1(
tid int primary key auto_increment,
tloc enum('南湖校区','浑湖校区')
)character set = utf8;
insert into person values('男','看电影,游泳,听音乐');
select * from person;
insert into department values(1,'数学系','李进','nanhu');
insert into department values(2,null,'李1','hunhu');
create table class(
classid char(8),
cla
)
案例一
begin; //开启事务
insert into dept (dname,loc) values('csb','zj');
insert into dept (dname,loc) values('yfb','gz');
rollback
案例二
隐式结束
隐式提交:当下列任意一种情况发生时,会发生隐式提交
执行一个DDL(CREATE、ALTER、DROP、TRUNCATE、RENAME)语句;
执行一个DCL(GRANT、REVOKE)语句;
隐式回滚:当下列任意一种情况发生时,会发生隐式回滚
客户端强行退出
客户端连接到服务器端异常中断
系统崩溃
begin; //开启事务
delete from dept;
create table type(
id int primary key auto_increment,
name varchar(30)
)
<<<<<<< .mine
begin;
insert into test values (1,'a');
insert into test values (2,'b');
savepoint s1;
insert into test values (3,'c');
insert into test values (4,'d');
delete from test where id in (1,3);
rollback to s1;
delete from test where id in (2,4);
commit;
||||||| .r7
=======
案例三 设置还原点、回滚点;注意了:这个两者操作不会结束事务
//设置还原点
savepoint 还原点的名称
rollback to 还原点的名
分析一
begin;
insert into dept(dname,loc)values('ceshibu','gz');
rollback; #当前事务结束了
insert into dept(dname,loc)values('yafabu','sz');
savepoint a;
insert into dept(dname,loc)values('manager','sz');
rollback;
分析二
begin;
insert into dept(dname,loc)values('ceshibu','gz');
rollback;
begin;
insert into dept(dname,loc)values('yafabu','sz');
savepoint a;
insert into dept(dname,loc)values('manager','sz');
rollback to a;
分析三
begin;
insert into dept(dname,loc)values('ceshibu','gz');
rollback;
>>>>>>> .r9
begin;
insert into dept(dname,loc)values('yafabu','sz');
savepoint a;
insert into dept(dname,loc)values('manager','sz');
savepoint b;
insert into dept(dname,loc)values('scb','sz');
rollback to b;
delete from dept;
commit;
SQL
|--DDL
|--DML insert update delete
|--TPL
|--DQL
|--SELECT
空值NULL
|--是一种特殊值,没有赋值不确定值
SELECT
-------------------------------------------
含义:DQL,用于检索数据
语法
select * || 列名 from 表名 [where=conditions]
算术运算符
|-- + - * / % 用于改变结果
|--优先级和数学是一样的。
|--可以通过() 改变优先级
案例空值处理
#mysql 自带的函数
#IFNULL(expr1,expr2)
select EMPNO,SAL*12 + ifnull(COMM,0) from emp;
列别名
|--语法
|--as alias
|--alias
|--案例
select EMPNO,SAL*12 + ifnull(COMM,0) as money from emp;
select EMPNO,SAL*12 + ifnull(COMM,0) money from emp;
|--注意点
|--如果别名有空格 或 特殊字符 需要添加 单引号 或 双引号
#消除重复行
语法
|--DISTINCT * || 列名1,列名n
select DISTINCT DEPTNO,EMPNO from emp;
#消除重复行
语法
|--DISTINCT * || 列名1,列名n
select DISTINCT DEPTNO,EMPNO from emp;
条件查询
|--select ... from 表名 where 条件表达式
//> >= < <= !=
|--
select * from emp where DEPTNO = 20
select * from emp where DEPTNO = 20 || DEPTNO = 30;
select * from emp where DEPTNO=20 and SAL > 1000;
select * from emp where DEPTNO NOT IN (20,30)
select * from emp where DEPTNO IN (20,30)
|--日期比较
|--注意:必须添加单引号包含
SELECT *FROM emp WHERE HIREDATE >'1985-01-01'
|--between 下限 and 上限 //包含边界
SELECT *FROM emp where sal BETWEEN 1000 AND 1500
|--like
SELECT *FROM emp where ENAME LIKE 'S%' #%任意个字符 _一个字符
SELECT *FROM emp where ENAME LIKE '%S%' #%任意个字符 _一个字符
SELECT *FROM emp where ENAME LIKE '%S_' #%任意个字符 _一个字符
//模糊查询中包含_ %的处理方式
select *from emp where JOB like 'MAN@_%' ESCAPE '@'
select *from emp where JOB like 'MAN@%%' ESCAPE '@'
|--is null is not null
select *from emp where MGR is null //查找老大
select *from emp where MGR is not null //查找被管理的员工
逻辑运算符
|--and
|--or
|--not
案例
... WHERE sal NOT BETWEEN 3000 AND 5000
... WHERE ename NOT LIKE 'D%’
|--排序(结果进行排序)
... order by 列名 || 别名 asc(默认) || desc
案例
|--select *from emp ORDER BY HIREDATE DESC
|--select *,12*sal + IFNULL(COMM,0) as money from emp ORDER BY money
|--SELECT ename, deptno, sal FROM emp ORDER BY deptno, sal DESC;
|--分页
语法
|--limit 跳过前面多少条,显示多少条
为什么要分页
|--性能
案例
#select *from emp limit 0,4; //page=1 pageSize=4
#select *from emp limit 4,4; //page=2 pageSize=4
#分页模型
select *from emp limit (page-1)*4,pageSize;
mysql函数
|--含义:内置,直接调用
|--分类
|--单行函数
|--多行函数
|--
数学函数
select ABS(9) as result from dual; //获取绝对值
select SQRT(4) FROM dual; //开平方
select SQRT(-4) FROM dual; //开平方
SELECT ROUND(rand()*50) FROM DUAL; //随机数加返回整数
select MOD(9,3) FROM dual; //求余数
SELECT CEIL(-9.1) FROM DUAL; //返回大于x的最小整数值
SELECT CEIL(9.1) FROM DUAL; //返回大于x的最小整数值
SELECT FLOOR(-9.1) FROM DUAL; //返回小于x的最大整数值
SELECT FLOOR(9.1) FROM DUAL; //返回小于x的最大整数值
SELECT ROUND(9.8) FROM DUAL; //返回整数
SELECT ROUND(9.86,1) FROM DUAL; #第二个参数如果是正数保留小数点多少位
SELECT ROUND(922.86,-2) FROM DUAL; 结果为1000,与四舍五入有点相似 #第二个参数如果是负数保留小数点左边多少位变成0
SELECT TRUNCATE(10.232412,4) FROM DUAL; TRUNCATE(x,y):截取函数,返回被舍弃的小数点后y位的数字x
SELECT log(exp(2)) FROM DUAL; //exp为e^2
//其他 sin cos log ....
字符串函数
CONCAT(s1,s2,…) //简单拼接
CONCAT_WS(x,s1,s2,…) //使用x作为分隔符拼接
INSERT(s1,x,len,s2); //x如果是负数含义??
LOWER (str)
UPPER(str)
LEFT(s,n)
RIGHT(s,n)
LPAD(s1,len,s2) //左边开始填充
RPAD(s1,len,s2) //右边开始填充
#select LTRIM(" abc ") from DUAL;
#select RTRIM(" abc ") from DUAL;
#select TRIM(" abc ") from DUAL;
SELECT rEPEAT('ABC',3) FROM DUAL;
比较字符串大小函数STRCMP(s1,s2):若所有的字符串均相同,则返回0,若根据当前分类次序,第一个参数小于第二个,则返回-1,其它情况返回1。
字符串替换函数REPLACE(s,s1,s2):将s字符串中的s1字符替换成s2。
SUBSTRING(s,n,len)
REVERSE(s)
select concat(upper(left(ename,1)),lower(right(ename,length(ename)-1))) as name ,length(ename) as namelength from emp where left(ename,1) like "J%" or
left(ename,1) like "A%" or left(ename,1) like "M%" ORDER BY ename asc ;
select round(datediff("2000-01-01",hiredate)/30,0) as time ,hiredate from emp;
日期和时间函数
|--CURDATE() 获取当前时间 年月日
//TODO
|--select TIMEDIFF('18:00:00',10000) from dual;
DATEDIFF //两个日期相差的天数
select DATEDIFF('2019-7-14','2019-7-1') from dual;
#%Y %m %d %H %i %S
DATE_FORMAT(date,format)
TIME_FORMAT(time,format)
SELECT DATE_FORMAT(now(),'%Y年%m月%d日 %H时%i分%S秒');
作业
流程控制函数
|--CASE
|--语法1 使用的场景:
CASE 值
WHEN '比较值1'
THEN '结果1'
WHEN '比较值2'
THEN '结果2'
END
|--CASE
WHEN 表达式 THEN '成立结果' ELSE '其他'
END
//薪水
//<= 4000
select
CASE
WHEN sal <=4000 THEN 'low'
ELSE 'height'
END
from emp;
|--IF
select if(sal<=4000,'low','height') from emp;
//TODO 工资分位三个档次
|--IFNULL
//..
|--NULLIF
//TODO
其他函数
|--MD5 不可逆的加密算法
//消息摘要
//密码加密
//文件校验(校验文件是否被人修改过)
-----------
碰撞破解
|--将常用的明文-->密文-->保存到数据库
关联查询
|--笛卡尔积
|--含义:两张表记录乘机
|--原因
|--没有设置关联的条件
等值关联查询
//查找员工编号姓名部门编号工作地点信息
select e.empno,e.ename,e.deptno,d.loc from emp e,dept d where e.deptno =d.deptno;
//查找员工编号姓名部门编号信息,但是工作地点是在NEW YORK
select e.empno,e.ename,e.deptno,d.loc from emp e,dept d where e.deptno = d.deptno and d.loc='NEW YORK';
非等值关联查询
//查看所有员工信息薪水级别
select e.*,g.grade from emp e,salgrade g where e.sal between g.losal and g.hisal
自关联
查询每个员工的姓名 和直接上级姓名 //TODO 没有上级领导的员工没有加载出来
select e1.ename,e2.ename from emp e1,emp e2 where e1.mgr=e2.empno;
多表连接的关键点
|--确定表
|--确定关系
3.查询每个经理所管理的人数,经理编号,经理姓名,要求包括没有经理的人员信息。
查询比自己部门平均工资高的员工姓名,工资,部门编号,部门平均工资
select e.ename,e.sal,e.deptno,em.avgsal
from emp e,(select deptno,avg(sal) as avgsal from emp group by deptno) em
where e.deptno=em.deptno
and e.sal>em.avgsal;
|--交叉查询
今日知识点
|--自然连接
|--连接条件:同名并且类型需要一样
如果名字一样,类型不一样会报错
|--using
|--可以指定具体列或者几列作为连接条件
|--on(编写连接条件)
select e.*,d.loc from emp e join dept d on e.DEPTNO = d.DEPTNO where 其他条件
select e.EMPNO,e.ENAME,e.job,e.mgr,d.loc,m.ENAME as '领导' from emp e join dept d on e.DEPTNO = d.DEPTNO JOIN emp m on e.MGR = m.EMPNO;
|--left join
语法:select *from 表1 left join 表2 on 表1和表2的关联条件
|--right join
语法:select *from 表1 right join 表2 on 表1和表2的关联条件
分组函数
|--含义:数据集合输入结果
|--count(求记录数) min(最小) max(最大) avg(平均值) sum(求和)
|--使用的地方
select //ok
having
order by
|--查询入职日期最早和最晚的日期
SELECT MIN(hiredate),max(hiredate) from emp;
|--查找工作是SALES开头的平均月薪,月薪总和
select AVG(sal),sum(sal)FROM emp where JOB like 'SALES%';
|--count(*) 推荐使用count(主键)
|--注意:返回满足条件的非空(NULL)行的数量
SELECT COUNT(DISTINCT deptno) FROM emp; //TODO 自行描述其含义
|--avg
|--注意:空(NULL)的不会参与计算,如果需要参与计算,可以参考下面的案例
select ceil(avg(ifnull(comm,0)))from emp;
GROUP BY
思路:但凡看到每个字眼基本上都用到group by 分组
语法:
select 只能出现gourp by 的分组依据、分组函数 from emp GROUP BY 列1,...
查询每个部门的编号,平均工资
select DEPTNO,AVG(SAL) from emp GROUP BY DEPTNO;
查询 每个部门 每个岗位 的工资总和。
select sum(sal) from emp GROUP BY DEPTNO,JOB
查询 每个部门 最高薪水 大于2000
select max(sal) from emp group by deptno HAVING max(sal) >= 3000
SELECT语句执行过程
//案例分析
select max(sal) maxSal,deptno from emp where deptno>20 group by deptno HAVING maxSal >= 3000
//from //给了表的别名
//where //不可以使用列的别名
//group by
//select
//having //可以使用列的别名
//order by
子查询
|--使用的位置
WHERE子句
HAVING子句
FROM子句
查询出比JONES为雇员工资高的其他雇员
select *from emp where sal > (select sal from emp where ename ='JONES')
显示 和雇员7369从事相同工作 并且工资大于雇员7876的 雇员的姓名和工作。
SELECT
ename,
job
FROM
emp
WHERE
job = (
SELECT
job
FROM
emp
WHERE
empno = 7369
)
AND sal > (
SELECT
sal
FROM
emp
WHERE
empno = 7876
)
查询工资最低的员工姓名,岗位及工资
select ename,job,sal from emp where sal = (select min(sal) from emp)
查询 部门最低工资比20部门最低工资高的 部门编号及最低工资
SELECT
deptno,
min(sal) minSal
FROM
emp
GROUP BY
deptno
HAVING
minSal > (
SELECT
min(sal)
FROM
emp
WHERE
deptNO = 20
)
#查询 经理的姓名,工资
select ename,sal from emp where empno in (select mgr from emp)
all
|--含义:满足全部条件即可。
>all 等价于 max
<all 等价于 min
=all
查询 部门编号不为20,且工资比20部门所有员工工资高的 员工编号,姓名,职位,工资。
SELECT
empno,
ename,
job,
sal
FROM
emp
WHERE
sal > ALL (
SELECT
sal
FROM
emp
WHERE
deptno = 20
)
AND deptno != 20;
#查询 部门编号不为10,且工资比 10部门所有员工 工资低 的 员工编号,姓名,职位,工资。
SELECT
empno,
ename,
job,
sal
FROM
emp
WHERE
sal < ALL (
SELECT
sal
FROM
emp
WHERE
deptno = 10
)
AND deptno != 10;
any
含义:有一个满足条件即可。
>any
<any
=any 等价于in
#查询 部门编号不为10,且工资 比10部门任意一名员工 工资高的 员工编号,姓名,职位,工资。
SELECT
empno,
ename,
sal
FROM
emp
WHERE
deptno != 10
AND sal > ANY (
SELECT
sal
FROM
emp
WHERE
deptno = 10
)
#查询 部门编号不为10,且工资 比10部门任意一名员工 工资低的 员工编号,姓名,职位,工资。
SELECT
empno,
ename,
sal
FROM
emp
WHERE
deptno != 10
AND sal < ANY (
SELECT
sal
FROM
emp
WHERE
deptno = 10
)
#查询是经理的员工姓名,工资
SELECT
ename,
sal
FROM
emp
WHERE
empno = ANY (SELECT mgr FROM emp)
在 FROM 子句中使用子查询
#查询 比 自己 部门平均工资高的 员工姓名,工资,部门编号,部门平均工资
SELECT
e.ename,
e.sal,
e.deptNo,
t.avgSal
FROM
emp e,
(
SELECT
avg(sal) avgSal,
deptNo
FROM
emp
GROUP BY
deptNo
) t
WHERE
e.DEPTNO = t.deptNo
AND e.sal > t.avgSal;
//TODO
子查询中的空值问题
SELECT
ename
FROM
emp
WHERE
empno NOT IN (SELECT mgr FROM emp);
子查询返回的结果中含有空值
上面的SQL语句试图查找出没有下属的雇员,逻辑上,这个SQL语句应该会返回8条记录,但是却一条也没返回,why?
因为子查询的结果中有一条空值,这条空值导致主查询没有记录返回。这是因为所有的条件和空值比较结果都是空值。因此无论什么时候只要空值有可能成为子查询结果集合中的一部分,就不能使用NOT IN 运算符
from里面放select的情况
总结:题目里有每种即涉及到group by 且要打印出分组函数下的值 如每种的什么什么和,平均什么什么,或者最低什么什么
1.查询部门平均工资在2500元以上的部门名称及平均工资。
select dept.dname,em.avgsal
from emp,dept,(select deptno,avg(sal) as avgsal from emp group by deptno ) em
where em.avgsal>2500 and emp.deptno=em.deptno and emp.deptno=dept.deptno
group by emp.deptno;
2.查询员工岗位中不是以“SA”开头并且平均工资在2500元以上的岗位及平均工资,并按平均工资降序排序。
select emp.job,em.avgsal
from emp,dept,(select deptno,avg(sal) as avgsal from emp group by job) em
where em.avgsal>2500 and emp.deptno=em.deptno and emp.deptno=dept.deptno and emp.job not like "SA%"
group by emp.deptno
order by em.avgsal desc;
3.查询部门人数在2人以上的部门名称、最低工资、最高工资,并对求得的工资进行四舍五入到整数位。
select dept.dname,round(min(emp.sal)),round(max(emp.sal))
from emp,dept,(select deptno,count(*) as num from emp group by deptno) em
where em.num>2 and emp.deptno=em.deptno and emp.deptno=dept.deptno
group by emp.deptno;
4.查询岗位不为SALESMAN,工资和大于等于2500的岗位及每种岗位的工资和。
select emp.job,em.sumsal
from emp,dept,(select deptno,sum(sal) as sumsal from emp group by job) em
where em.sumsal>=2500 and emp.deptno=em.deptno and emp.deptno=dept.deptno and emp.job !="salesman"
group by emp.job;
5.显示经理号码和经理姓名,这个经理所管理员工的最低工资,
没有经理的KING也要显示,不包括最低工资小于3000的,按最低工资由高到低排序。
6.查询工资高于编号为7782的员工工资,并且和7369号员工从事相同工作的员工的编号、姓名及工资。
7.查询工资最高的员工姓名和工资。
select ename,sal
from emp e,(select max(sal) as maxsal from emp )em
where e.sal=em.maxsal;
;
8.查询 部门最低工资高于10号部门最低工资的 部门的编号、名称及部门最低工资。
select e.deptno,d.dname,em.minsal
from emp e,dept d, (select min(sal) as minsal10 from emp where deptno=10 )em10, (select deptno,min(sal) as minsal from emp group by deptno )em
where e.deptno=d.deptno and e.deptno=em.deptno and em.minsal>em10.minsal10
group by e.deptno;
9.查询员工工资为其部门最低工资的员工的编号和姓名及工资。
10.显示经理是KING的员工姓名,工资。
11.显示比员工SMITH参加工作时间晚的员工姓名,工资,参加工作时间。
12.使用子查询的方式查询哪些职员在NEW YORK工作。
13.写一个查询显示和员工SMITH工作在同一个部门的员工姓名,雇用日期,查询结果中排除SMITH。
14.写一个查询显示其工资比全体职员平均工资高的员工编号、姓名。
15. 显示部门名称和人数
16. 显示每个部门的最高工资的员工
17. 显示出和员工号7369部门相同的员工姓名,工资
18. 显示出和姓名中包含“W”的员工相同部门的员工姓名
4.查询部门人数大于所有部门平均人数的的部门编号,部门名称,部门人数
select e.deptno,d.dname,count(e.ename) as num
from emp e,dept d
where e.deptno=d.deptno
group by deptno
having num>all (select avg(e.ename) from emp group by deptno);
(solor)
1.创建一个视图,通过该视图可以查询到工资在2000-5000内并且姓名中包含有A的员工编号,姓名,工资。
create view sal2000
as select deptno,ename,sal
from emp
where sal between 2000 and 5000;
select *from sal2000
desc sal2000
1.创建视图v_emp_20,包含20号部门的员工编号,姓名,年薪列(年薪=12*(工资+奖金);
2.从视图v_emp_20中查询年薪大于1万元员工的信息;
3.请为工资大于2000的员工创建视图,要求显示员工的部门信息,职位信息,工作地点;
4.针对以上视图执行insert,update,delete,语句能否成功,为什么?
|--用户和权限管理
|--登录 需要校验账号密码:
|--host
|--user/password
|--授权 判断用户当前操作是否有权限
权限表共有6个表:user、db、host、tables_priv、 columns_priv和procs_priv。
当MySQL服务启动时,会首先读取MySQL中的权限表,并将表中的数据装入内存。当用户进行存取操作时,MySQL会根据这些表中的数据做相应的权限控制。
|--User表中的权限是全局的
比如:
Insert_priv:Y
含义:当前用户能对所有数据库的所有表都有插入权限
Insert_priv :N
含义:当前用户 不能对所有数据库的所有表都有插入权限;如果插入需要进一步权限校验
|--db
|--存储了用户对某个数据库的操作权限
|--tables_priv
|--记录用户对哪个数据库的哪张表的权限
|--column_priv
|--列的权限
------------------------------------------------------
mysql安全
|--验证
|--User表中判断hostuserpassword
|--授权校验流程
if(User表校验权限(全局)){
执行操作
}else if(从DB表校验权限){
执行操作
}else if(从table_priv表校验权限){
执行操作
}else if(从column_priv表校验权限){
执行操作
}else{
报错,没有权限
}
创建用户
CREATE USER 用户名[IDENTIFIED BY [PASSWORD]'password']
[,user[IDENTIFIED BY [PASSWORD]'password']][,…];
create user 'crm'@'localhost' identified by '123456';
创建用户并且授权
GRANT priv_type ON database.table
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] [,…]
[WITH GRANT OPTION];
//授权的权限
GRANT INSERT ON crm.* TO 'crm'@'localhost' identified by '123456' WITH GRANT OPTION;
GRANT INSERT ON crm.emp TO 'otherCrm'@'localhost' identified by '123456' WITH GRANT OPTION;
1.自己尝试创建一个用户user1,并授予所有数据表的SELECT和UPDATE权限
create user user_1 identified by '123456';
grant select on user_1.emp to 'otherCrm' identified by '123456' with grant option;
创建用户
语法:
CREATE USER 用户名[IDENTIFIED BY [PASSWORD]'password']
[,user[IDENTIFIED BY [PASSWORD]'password']][,…];
案例:
create user 'crm'@'localhost' identified by '123456';
创建用户并且授权
语法:
GRANT priv_type ON database.table
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] [,…]
[WITH GRANT OPTION]; //授权的权限
案例:
GRANT INSERT ON crm.* TO 'crm'@'localhost' identified by '123456' WITH GRANT OPTION;
GRANT INSERT ON crm.emp TO 'otherCrm'@'localhost' identified by '123456' WITH GRANT OPTION;
//删除账户并清理权限
DROP USER otherCrm@localhost; //删除账号并且清除对应的授权信息
//修改账户名
//语法:
RENAME USER old_user TO new_user,[, old_user TO new_user] [,…];
//案例
rename user haha@localhost to haha2@localhost;
//修改其他用户的密码
语法:ALTER USER userIDENTIFIED BY 'password';
案例:
ALTER USER for crm@localhost IDENTIFIED BY '*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B';
//修改密码
//修改指定账户的密码
语法:SET PASSWORD FOR [user]= PASSWORD('newpassword');
案例:SET PASSWORD crm@localhost = PASSWORD('ROOT');
//修改自己的密码(需要重新登录)
SET PASSWORD =PASSWORD('123456');
-------------------------------------
授权管理
GRANT语句的基本语法格式如下。
GRANT priv_type [(column_list)] [,priv_type [(column_list)]] [,…n]
ON {table_name|*|*.*|database_name.*|database_name.table_name}
TO user[IDENTIFIED BY [PASSWORD] 'password']
[,user[IDENTIFIED BY [PASSWORD] 'password']] [,…n]
[WITH GRANT OPTION];
//准备环境(自行准备)
创建CRM账户:
对crm数据库所有的表都有插入的权限
//案例 赋值权限案例
//赋值删除权限
grant delete on crm.* to crm@localhost
//赋值更新权限
//赋值更新所有列的权限
grant update on crm.emp to crm@localhost
//赋值更新指定列的权限
grant update(empno) on crm.emp to crm@localhost
//案例 收回权限
语法:
REVOKE ALL PRIVILEGES,GRANT OPTION
FROM 'username'@'hostname'[,'username'@'hostname'][,…n];
案例
//收回所有权限,包括GRANT权限
revoke all privileges,grant option from crm@localhost;
//grant option代表包括grangt权限
//收回crm账号更新empno列的权限
revoke update(empno) on crm.emp from crm@localhost;
//显示已经授予的权限
语法:
show grants for 账号;
案例:
show grants for crm@localhost;
MYSQL编程
|--过程
|--变量
SET @user_variable1=expression1
[,user_variable2= expression2 , …]
set @java = '1.8';
set @mysqldb = '5.x';
set @result = concat(@java,@mysqldb);
select @result;
set @maxEmpNo = (select max(empNo) from emp);
select @maxEmpNo;
--------------
set @maxEmpNo = (select max(empNo) from emp);
select @maxEmpNo;
select *from emp where empno = @maxEmpNo;
//系统变量
//@@ @@version
//CURRENT_USER
|--存储过程
|--含义:
是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。
存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程字并给定参数(需要时)来调用执行
简单而言:就是数据库 SQL 语言层面的代码封装与重用。
|--优点
|--存储过程在服务器端运行,执行速度快。
|--存储过程执行一次后,其执行规划就驻留在高速缓冲存储器,在以后的操作中,只需从高速缓冲存储器 中调用已编译好的二进制代码执行,提高了系统性能。
|--封装内部实现细节,确保数据库的安全
|--缺点
|--不同数据库产品的语法有些不同,切换数据库产品需要重新编写对应数据库的存储过程。
|--语法
CREATE PROCEDURE 存储过程名 ([参数[,...]])
存储过程体
|--参数说明:
[ IN | OUT | INOUT ] 参数名 类型
|--DELIMITER关键字
|--含义:关键子,用来指定MySQL语句的结束标志修,默认的结束符是(;),放在定义存储过程
或函数前面。
一般操作:
|--DELIMITER $$ //修改语句结束符为$$
|--DELIMITER ; //恢复结束符为;
|--局部变量
局部变量含义:在beign end之间定义的变量
局部变量定义语法:
DECLARE 局部变量名 类型 [default 默认值]
|--案例一 编写一个存储过程,实现的功能是删除一个特定会员的信息
DELIMITER $$
create procedure pro_del_member(in memberId char(18))
BEGIN //相当于是{
delete from members where 身份证号 = memberId;
END $$ //相当于是}
DELIMITER ;
|--案例二 在存储过程中使用局部变量并结合SELECT...INTO语句
DELIMITER $$
create procedure init_mul_variables(in memberId char(18),out resultId char(18),out resultName(varchar(30)) )
BEGIN
DECLARE resultMemberId char(18);
DECLARE resultMemberName varchar(30);
select 身份证号,会员姓名 into resultMemberId,resultMemberName from members where 身份证号 = memberId;
set resultId = resultMemberId;
set resultName = resultMemberName;
END $$
DELIMITER ;
|--调用
CALL 过程名([参数1,参数...])
|--SHOW PROCEDURE STATUS //列出有多少过程
|--SHOW CREATE PROCEDURE init_mul_variables //详情
|--删除存储过程
DROP PROCEDURE [IF EXISTS] 存储过程名
--------------------------------------------------------------
存储过程控制语句
|--IF
IF 条件1 THEN 语句序列1
[ELSEIF条件2 THEN语句序列2] ...
[ELSE 语句序列e]
END IF
创建存储过程,判断两个输入的参数哪一个更大
DELIMITER $$
create procedure compareMax(in param1 int,in param2 int,out result varchar(20))
BEGIN
IF
param1 > param2 THEN SET result = concat(param1,'>',param2);
ELSEIF param1 < param2 THEN SET result = concat(param1,'<',param2);
ELSE SET result = concat(param1,'=',param2);
END IF;
END $$
DELIMITER ;
call compareMax(1,2,@result);
select @result;
|--CASE
CASE 表达式
WHEN 值1 THEN 语句序列1
[WHEN值2 THEN语句序列2] ...
[ELSE语句序列e]
END CASE;
或者:
CASE
WHEN 条件1 THEN 语句序列1
[WHEN条件2 THEN语句序列2] ...
[ELSE语句序列e]
END CASE;
案例:
创建一个存储过程,当给定参数为U时返回“上升”,给定参数为D时返回“下降”,给定其他参数时返回“不变”。
DELIMITER $$
create procedure judge1(in param char(1),out result varchar(20))
BEGIN
CASE param
WHEN 'U' THEN SET result = "上升";
WHEN 'D' THEN SET result = "下降";
ELSE SET result = "不变";
END CASE;
END $$
DELIMITER ;
DELIMITER $$
create procedure judge2(in param char(1),out result varchar(20))
BEGIN
CASE
WHEN 'U'=param THEN SET result = "上升";
WHEN 'D'=param THEN SET result = "下降";
ELSE SET result = "不变";
END CASE;
END $$
DELIMITER ;
|--循环
while
WHILE语句语法格式为:
[开始标号:] WHILE条件 DO
程序段
END WHILE [结束标号]
DELIMITER $$
create procedure fiveEach(out result varchar(100))
BEGIN
DECLARE a int default 5;
set result = '';
WHILE a >0 DO
set a = (a-1);
set result = concat(result,a);
END WHILE;
END $$
DELIMITER ;
call fiveEach(@result);
select @result;
//////////
REPEAT语句格式如下:
[开始标号:] REPEAT
程序段
UNTIL 条件
END REPEAT [结束标号]
DELIMITER $$
create procedure fiveEach(out result varchar(100))
BEGIN
DECLARE a int default 5;
set result = '';
END $$
DELIMITER ;
//LOOP语句
-----------------------------
自定义函数
|--和过程的区别
|--自定义函数没有输出参数 out
|--不能通过call调用
|--return 过程是没有return
语法
CREATE FUNCTION 自定义函数名 ([参数[,...]])
RETURNS 类型
函数体
//查找图书数量
DELIMITER $$
create function findEmpCount()
returns int
BEGIN
return (select count(*) from emp);
END $$
DELIMITER ;
//SHOW FUNCTION STATUS
创建一个自定义函数,返回emp表中id 姓名
DELIMITER $$
create function findByEmpNo(empnoParam varchar(30))
returns varchar(30)
BEGIN
return (select ename from emp where empno = empnoParam);
END $$
DELIMITER ;
select findByEmpNo(7369) from dual;
#
CREATE TRIGGER 触发器名 触发时间 触发事件
ON 表名 FOR EACH ROW 触发器动作
/
创建一个表table1,其中只有一列a。
在表上创建一个触发器,每次插入操作时,将用户变量str的值设为“TRIGGER IS WORKING”。
CREATE TABLE table1(a INTEGER);
create trigger talbe1Trigger after insert on table1 for each row
SET @str= ' TRIGGER IS WORKING';
INSERT INTO table1 VALUES(10);
#级联删除
DELIMITER $$
CREATE TRIGGER dept_del before DELETE
ON dept FOR EACH ROW
BEGIN
DELETE FROM emp WHERE deptno = OLD.deptno;
END$$
DELIMITER ;
//
假设数据库中有一个与Members表结构完全一样的表member_backup,
创建一个触发器,在Members表中添加数据的时候,
//
调用存储过程,将member_backup表中的数据与Members表同步。
//批量添加
//增量
//member_back member
//id //id
//获取member_back 主键的最大值
//获取member 主键的最大值
if(==){
}else if(获取member主键 > 获取member_back主键){
遍历 5 2
id = 3 4 5
}
首先,定义存储过程:创建一个与Members表结构完全一样的表
//java 基础
//1.8
//
DELIMITER $$
create procedure init_mul_variables(in memberId char(18),out resultId char(18),out resultName varchar(30))
BEGIN
DECLARE resultMemberId char(18);
DECLARE resultMemberName varchar(30);
select 身份证号,会员姓名 into resultMemberId,resultMemberName from members where 身份证号 = memberId;
set resultId = resultMemberId;
set resultName = resultMemberName;
END $$
DELIMITER ;
1.
DELIMITER $$
create procedure init_delete(in memberId char(18))
BEGIN
delete from members where 身份证号=memberId ;
END $$
DELIMITER ;
call init_delete('430103198608201963');
SHOW PROCEDURE STATUS //列出有多少过程
SHOW CREATE PROCEDURE init_mul_variables //详情
ppt30例
DELIMITER $$
CREATE PROCEDURE dj_update(IN c_name CHAR(8), IN b_name CHAR(20))
BEGIN
DECLARE bh CHAR(20);
DECLARE sfz CHAR(18);
DECLARE sl TINYINT;
SELECT 身份证号 INTO sfz FROM Members WHERE 会员姓名=c_name;
SELECT 图书编号 INTO bh FROM Book WHERE 书名=b_name;
SELECT 订购册数 INTO sl FROM Sell WHERE 身份证号=sfz AND 图书编号=bh;
IF sl>=5 AND sl<=10 THEN
UPDATE Sell SET 订购单价=订购单价*0.9 WHERE 身份证号=sfz AND 图书编号=bh;
ELSE
IF sl>10 THEN
UPDATE Sell SET 订购单价=订购单价*0.8 WHERE 身份证号=sfz AND 图书编号=bh;
END IF;
END IF;
END$$
DELIMITER ;
调用存储过程dj_update:
CALL dj_update ('张三', '网络数据库');
DELIMITER $$
create procedure init_count(in memberName char(10),in bookName varchar(40),out result varchar(20) )
begin
declare bookNum TINYINT;
declare memberid char(18);
declare bookid char(20);
select 身份证号 into memberid from members where 会员姓名=memberName ;
select 图书编号 into bookid from book where 书名=bookName ;
select 订购册数 into bookNum from sell where 身份证号=memberid and 图书编号=bookid;
if bookNum<5 then
set result="不打折";
else
if bookNum>=5 and bookNum<=10 then
set result="打9折";
else if bookNum>10 then
set result="打8折";
end if;
end if;
end if;
end $$
DELIMITER ;
CALL init_count ('王林', '网络数据库');