MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
本篇文章所介绍的版本为MySQL8.0.3
DDL:数据定义语言–创建删除修改库、表结构(主要关键字:create、alter、drop和truncate)
DML:数据操作语言–增删改查数据(主要关键字:select 、insert、update和delete)
DQL:数据查询语言–查数据 (主要关键字:select)应用中对数据的查询的操作频率远高于数据的增删改.
DCL:数据控制语言–用户和授权(主要关键字:grant和revoke)
列类型 | 说明 |
---|---|
tinyint/smallint/mediumint/int/bigint | 1字节/2字节/3字节/4字节/8字节整数,又可分为有符号和无符号两种。这些整数类型的区别仅仅是表示的范围不同。 int默认最多11位, int(2) 必须是2位数字 |
float/double | 单精度、双精度浮点类型 |
decimal/dec | 精确小数类型,相对于float和double不会产生精度丢失的问题 decimal(6,2) |
date | 日期类型,不能保存时间,当把Java中的Date对象保存到date列时,时间部分丢失 |
time | 时间类型,不能保存日期,当把Java中的Date对象保存到date列时,日期部分丢失 |
datetime | 日期、时间类型 |
timestamp | 时间戳类型 不能没有值. 默认是系统当前时间. yyyy-MM-dd |
year | 年类型,仅仅保存时间的年份 |
char | 定长字符串类型 char(10) 必须是10个字符的字符串 |
varchar | 可变长度字符串类型 **** varchar(10) 最多10个字符 |
binary | 定长二进制字符串类型,它以二进制形式保存字符串 |
varbinary | 可变长度的二进制字符串类型,它以二进制形式保存字符串 |
tinyblob/blob/mediumtblob/longblob | 1字节/2字节/3字节/4字节的二进制大对象,可以用于存储图片,音乐等二进制数据,分别可存储255B/64KB/16MB/4GB大小 |
tinytext/textmediumtext/longtext | 1字节/2字节/3字节/4字节的文本对象,可以用于存储超长的字符串,分别可存储255B/64KB/16MB/4GB大小的文本 |
关系型数据库的操作语言:sql Structured Query Language
结构化查询语言,不同的数据库少量的自己的"方言”。
关键字的大小写不区分,语句以;结束.可以使用空格和换行增加可读性。
sql的代码不是开发代码,是操作代码,因此有的时候不能重复运行
create database 库名;
#创建一个名为“db”的库,不可以重复运行
create database db;
如果重复运行上述代码,会提示:[Err] 1007 - Can’t create database ‘e5758db’; database exists
通常可以将代码修改为
create database if not exists 库名;
#可以重复运行
create database if not exists db;
如果不存在库db,则创建库db
drop database 库名;
#不可重复运行
drop database db;
重复运行上述代码及不存在该库时,会提示[Err] 1008 - Can’t drop database ‘db’; database doesn’t exist
同样可以改写为
drop database if exists 库名;
#可以重复运行
drop database if exists db;
如果存在库db,则删除库db
在控制台中直接用命令操作库的时候,必须选择要操作的数据库
use 库名;
use db;
显示所有的数据库
show database;
显示当前数据库里的所有表
show tables;
显示当前数据库的编码
(like:模糊查询 字符串数据要是使用单引号 %:任意个数的任意字符)
show variables like '%character%';
create table student(
-- 列名 列类型 约束(数据库提供的针对市局的规则
sid int primary key auto_increment,
sname varchar(20),
sage int,
ssex char(1) default '女',
sdisplay char(100) unique
)
desc student; -- 查询表结构
在mysql数据库里,无论该列的数据是什么类型,都可以使用null赋值。
主键约束:主键列,这一列的值要求非null,是唯一的,是跟表的主体信息无关的一列,作用是唯一标识一行数据。
通常主键要么使用整数,设置自动增长属性,要么UUID(32位随机16进制字符串和4个“-”,共36位)
增加列
一个字段:alter table 表名 add 列名 列类型 约束;
如果为表增加两个及以上字段需要使用圆括号
多个字段alter table 表名 add (列名1 列类型1 约束1,…,列名2 列类型2 约束2);
alter table student add(
sdisplay char(100) unique,
saddress varchar(20),
remark varchar(100)
);
修改列定义
将stu表中的字段sdisplay修改为varchar类型,长度为255
alter table 表名 modify 新列名 新列类型;
alter table student modify sdisplay varchar(255);
删除列
alter table 表名 drop 删除列;
alter table student drop remark;
重命名表
alter table 表名 rename to 新表名;
alter table student rename to stu;
drop table 表名;
drop table stu;
-- insert into 表 (要插入的数据的列1,...,要插入的数据列2) values (列1的值,...,列2的值)
insert into stu (sname,sdisplay) values ('许三多','士兵突击');
-- 不指定列,全部插入,依次给值
insert into stu values (null,'张三',19,'男','最强配角','山东');
-- update 表 set 列1 = 值1,...,列n = 值n where 列 = 值 and/or ...;
update stu set sage = 28,saddress='济南'where sname = '许三多';
-- 针对字符串类型的数据,可以进行模糊查询 ——:1个任意字符 %:任意个任意字符
update stu set sdisplay = '影视演员' where sage=19 and sname like '李%';
删除数据要谨慎!!!
#delete from 表;删除表中的所有行数据
#delete from 表 where 条件;
delete from stu where sage = 19 and ssex = '男';
#DDL里的删除 truncate table stu;
truncate table stu;
#逻辑删除,给表增加一列代表数据的可用状态
alter table stu add state int(1) default 1;
update stu set state = 2 where sid = 1;
select 字段 from 表
select empno,ename,sal from emp;
select * from emp;
where加条件(可以使用运算符和一些关键字)
运算符和关键字: > >= < <= != = <> is null not and or in(值1,值2) between 10 and 20
select * from emp where sal >= 8000 and sal<=30000;
select * from emp where sal between 8000 and 30000;
select ename,sal,comm from emp where comm is not null;
select * from emp where job in ('文员','董事长');
#mysql数据库里,时间类型可以直接和字符串一起运算或赋值、修改等
select * from emp where hiredate > '2002-02-02';
去除重复列,很少使用
select distinct job from emp;
起别名,场景:多表查询时,给表或字段起别名
select ename as '员工姓名' ,empno '员工编号',mgr '领导编号' from emp;
select e.* from emp e;
select e,ename,e.sal from emp e;
去空null,在mysql里,任何数据跟null运算结果都是null
查询员工名,月薪,奖金,月薪和奖金和
select ename ,sal,comm,(sal+comm) as '月薪和奖金和' from emp;
-- IFNULL(expr1,expr2)如果expr1是null,则用expr2替换
select ename,sal,comm, (sal+IFNULL(comm,0)) as '月薪和奖金和' from emp;
字符串类型的列可以做模糊查询,_ %(%任意个数任意字符)
select * from emp where ename like '__';
select * from emp where ename like '%张%';
select * from emp where hiredate like '%2007%';
update emp set hiredate = '2019-02-22' where empno = 1002;
order by 列 升序asc/降序desc
按照sal的升序,入职日期的降序查询所有销售员的信息.
select * from emp order by sal asc,hiredate desc;
select * from emp where job = '销售员' order by sal asc,hiredate desc;
对列做纵向运算的查询,自动排除null,sum(sal),max(sal)min()avg()count()
select max(sal),min(sal),avg(sal),sum(sal),count(mgr) from emp;
计算15个人的平均奖金
select avg(comm) from emp;
select avg(IFNULL(comm,0)) from emp;
count(*) *:所有列/一行
select count(*)from emp;
select count(empno) from emp;
计算15人里月薪和奖金总和最小的值,和最大的值。
select min(sal+IFNULL(comm,0)),max(sal+IFNULL(comm,0)) from emp;
分组一般都捎带着聚合计算
查询销售员和文员这2个工作的人数。
select job,count(*) from emp group by job;
分组后使用条件筛选结果 使用having
select job,count(*) from emp group by job having job in('文员','销售员');
分组使用条件筛选出要参与分组聚合计算的数据,然后再分组
查询emp表中,按照部门号分,每个部门里工资大于15000的人数
select deptno,count(*) from emp where sal>15000 group by deptno;
select deptno,count(*) from emp where sal>15000 group by deptno order by count(*) asc,deptno desc;
查询emp表中.按照部门号分.每个部门里工资大于15000的人数
显示的时候,按照人数的升序显示,部门号降序显示,且只显示人数高于1人的部门
select deptno,count(*)
from emp where sal>15000 group by deptno having count(*)>1 order by count(*) asc,deptno desc;
limit 记录的下标,记录的条数;
select * from emp order by empno desc limit 0,4;-- 每页显示4条,查询第1页
select * from emp order by empno desc limit 4,4;-- 每页显示4条,查询第2页
select * from emp order by empno desc limit 8,4;-- 每页显示4条,查询第3页
select * from emp order by empno desc limit 12,4;-- 每页显示4条,查询第4页
pageSize:每页显示几条,page:第几页
limit(page-1)*pageSize,pageSize;
把两个单独查询的结果竖向叠在一起,要求:两个单独的查询的结果集的表结构要一致
select ename,job,sal from emp where job = '文员'
union
select ename,job,sal from emp where job = '经理' and sal > 27777;
把有主外键关系的表的表头横向连接在一起,两个表里的数据进行组合得到一个“大表”
内连接:把两个表连在一起 sql官方语言为inner join , mysql方言:为“,”
-- emp和dept具有外键关系,但是没有使用外键约束限制,所以在emp中,有一条张二数据他的部门号50,没在dept表里
select e.* , d.* from emp e, dept d;
-- 使用where条件,将无用的组合去除
select e.* , d.* from emp e, dept d where e.deptno = d.deptno;
-- SQL
select e.* , d.* from emp e inner join dept d on e.deptno = d.deptno;
-- 查询所有文员的姓名,工作,月薪,部门号,部门名
select e.ename,e.job,e.sal,e.deptno,d.dname from emp e inner join dept d on e.deptno = d.deptno where e.job = '文员';
外连接:以某个表为主要查询表,表里的数据要一定查询出来,连接的表中如果没有对应的数据,则查询null
left join 左外连:左边的表全查出 right join 右外连:右边的表全查出
select e.*,d.* from emp e left join dept d on e.deptno = d.deptno;
select e.*,d.* from emp e right join dept d on e.deptno = d.deptno;
自然连接:两个表的内连接,系统自动寻找主外键关系列来限制数据的组合,去除无用组合
select e.*,d.* from emp e natural join dept d;
示例
(1):查询emp表中,每个部门编号、部门员工人数、部门中员工的月薪和奖金和,这个部门名字和所在地
select e.deptno,count(*) '部门员工人数',sum(sal+ifnull(comm,0)) '月薪和奖金和',d.dname,d.loc
from emp e left join dept d on e.deptno = d.deptno group by e.deptno;
(2):查询每个员工的名字、工作、月薪、还有所在部门的部门名和地点,只差部门地点在北京和上海的那些员工信息
select e.ename,e.job,e.sal,d.dname,d.loc
from emp e left join dept d on e.deptno = d.deptno
where d.loc in ('北京','上海');
(3)查询入职日期早于领导入职日期的员工名、员工入职日期、领导名、领导入职日期
select e.ename,e.hiredate,m.ename,m.hiredate,monthname(e.hiredate) as '员工入职月份'
from emp e left join emp m on e.mgr = m.empno
where e.hiredate < m.hiredate and monthname(e.hiredate) = 'December';
(4):查询入职日期早于领导入职日期的员工名、员工入职日期、领导名、领导入职日期、员工所在部门名和地点
select e.ename,e.hiredate,m.ename,m.hiredate,e.deptno,d.dname,d.loc
from emp e left join emp m on e.mgr = m.empno left join dept d on e.deptno = d.deptno
where e.hiredate < m.hiredate;
(5):查询emp中,各个部门号、部门名和这个部门里员工入职日期早于领导入职日期的人数
select e.deptno,count(*),d.dname
from emp e left join emp m on e.mgr = m.empno left join dept d on e.deptno = d.deptno
where e.hiredate < m.hiredate
group by e.deptno;
(6):查询emp中,各个部门号、部门里的人数、最大工资、最小工资和这个部门所在地,只显示最大工资最多的两个部门
select e.deptno,count(e.empno),max(e.sal),min(e.sal),d.dname
from emp e left join dept d on e.deptno = d.deptno
group by e.deptno
order by max(e.sal) desc
limit 0,2;
(7):查询入职日期早于领导入职日期 并且 员工月薪大于25555的
员工名,入职日期,领导名,领导入职日期,员工月薪,领导月薪,员工部门名,员工部门地点,领导部门名,领导部门地点
select e.ename,e.hiredate,m.ename,m.hiredate,e.sal,m.sal,d.dname,d.loc,dm.dname,dm.loc
from emp e left join emp m on e.mgr = m.empno left join dept d on e.deptno = d.deptno left join dept dm on m.deptno = dm.deptno
where e.hiredate < m.hiredate and e.sal > 25555;
子查询可以作为另外一个查询的条件或者是表
子查询作为条件
-- 查询工资高于关羽的员工名字和工资
select ename,sal from emp where sal > (select sal from emp where ename = '关羽');
子查询作为表(这个例子并不好,只是为了演示如何使用这种查询方法)
-- 查询入职日期早于领导的员工的名字、部门号、部门名 从入职日期早于领导的员工的名字、日期、领导名字、日期的表里查询
select w.ename,w.deptno,d.dname
from (select e.ename,e.hiredate,m.ename 'mname',m.hiredate 'mdate',e.deptno
from emp e left join emp m on e.mgr = m.empno where e.hiredate < m.hiredate) w
left join dept d on w.deptno = d.deptno;
使用关键字:any(随便一个),all(所有的)
#查询工资高于所有20部门员工工资的员工信息
select *from emp where sal > all(select sal from emp where deptno = 20);
示例
(1)查询emp表中,每个部门中,(工资高于各部门平均工资最低的部门的那个部门的平均工资)的人数和部门名和所在地
select e.ename,count(*),d.dname,d.loc
from emp e left join dept d on e.deptno = d.deptno
where e.sal > (select avg(sal) avgsal from emp group by deptno order by avgsal asc limit 0,1)
group by e.deptno;
(2)各部门平均工资最低的部门的那个部门的平均工资
select avg(sal) avgsal from emp group by deptno order by avgsal asc limit 0,1;
视图 view 是基于某个查询的结果产生的表。创建之后可以保存,方便以后进行查询
原表数据发生改变,视图跟随改变,视图不允许主动做改变
#入职日期早于领导的员工的姓名员工,入职日期,部门号,领导名,领导入职日期
create or replace view emp_mgr as
select e.ename empname,e.hiredate empdate,e.deptno,m.ename mgrname,m.hiredate mgrdate
from emp e left join emp m on e.mgr = m.empno where e.hiredate < m.hiredate;
#入职日期早于领导的员工的员工名,部门号,部门名
select em.empname,em.deptno,d.dname
from emp_mgr em left join dept d on em.deptno = d.deptno;
了解索引
作用:类似书的目录,加速对表中数据的查询。由数据库在查询数据时使用。
创建:
1自动创建,创建表时,表的主键列自动创建索引,表中具有唯一约束的列,自动创建索引。
2手动创建,create index 名字 on 表 (哪些字段)
#先创建一个表来演示
create table tcat(
cid int primary key auto_increment,
cname varchar(20) unique,
cdisplay varchar(100),
ccolor varchar(10),
cage int,
ctype varchar(10)
);
#假如业务中经常按照猫的描述和品种去查询,而且数据库中猫的数据量巨大。
create index dis_type on tcat (cdisplay,ctype);
DCL(创建删除用户,授权撤销用户权限)
查看所有用户:打开mysql库里的user表,就可以看到所有用户
创建用户,用户名“aaa”,限制此用户名在localhost这个主机上使用,密码是“123456”
create user 'aaa'@'localhost' identified by '123456';
授权:
将 某个/某些 在 哪个库上的哪个/哪些表的权限 授予给用户
grant all on ejob.* to 'aaa'@'localhost';
flush privileges; -- 刷新权限
移除权限
revoke权限1, … , 权限n on 数据库.* form 用户名
revoke create,alter,drop on mydb1.* from user1@localhost;
更改密码
use mysql;
update user set password=password(‘新密码’) where user=’用户名’ and host=’ip’;
flush privileges;