MYSQL数据库练习笔记
一.准备操作
启动mysql服务器:
net start mysql
关闭mysql服务器:
net stop mysql
登陆客户端数据库:
mysql -u用户名 -p密码
二.DDL
删除数据库
drop 数据库名
使用/切换数据库
use 数据库名
展示数据库
show databases;
查看表
show tables;
创建表
create table 表名 (name varchar(30),age int;socre int);
删除表
drop table 表名
展示表结构
desc 表名
查看创建表的语句
show create table 表名;
修改表
添加列:
alter table 表名
add(
列名 类型;
列名 类型
)
在第一个位置增加:
alter table 表名
add 列名 类型 first;
在指定列后添加:
alter table 表名
add 列名 类型 after 在那一列添加;
修改列类型:
alter table 表名
modify 列名 新列类型
修改列名:
alter table 表名
change 原列名 新列名 列类型
删除列:
alter table 表名
drop 列名
修改表名称:
alter table 表名
rename to 新表名;
三.DML
插入数据
INSERT INTO user(Name,age,socre)VALUES('lisi',18,19);
insert into user(name,age,socre)values('wangwu',45,34);
insert into student values ('itcast_001','zhangsan',15,'nv',78.9);
insert into student values ('itcast_002','lisi',20,'nan',88.9);
insert into student values ('itcast_003','wangwu',49,'nv',90.9);
insert into student values ('itcast_004','zhaoliu',28,'nan',70.9);
insert into student values ('itcast_005','huangjin',35,'nv',78.9);
insert into student values ('itcast_006','linchi',19,'nan',68.8);
insert into student (id,name,age,sex,score) values('itcast_009','hanCheng',35,'nan',90.1);
修改表数据:
update 表名 set 列名=值…… where 列名=值;
update student name='zhangsan' where id='001';
删除表数据:
delete from student where id='001';
delete from studnet where name='zhangsna';
delete from student where name='lisi';
四.DQL
全部信息查询:
select * from studnet;
按列名查询+范围:
select name,age,id from student from age>20;
select name,age,id from student from age between 20 and 50;
select name,age,id from student from age>20 and age<50;
模糊查询:
select *from student where name like '%xx%';
去重复查询:
select distin sex from student;
操作查询:
select *, age=age+10 from student;
列起别名:
select id ID,name NAME,age AGE,score SCORE from student;
排序查询:
select * from student order by age ASC;//升序
select * from student order by age desc;//降序
select * from student order by age desc,score asc;//先按年龄降序,年龄相同在按成绩升序
使用聚合函数查询:
count():统计指定列不为null的记录行数;
max():计算指定列的最大值,如果指定列是字符串的类型,那么使用字符串的排列顺序运算;
min():计算指定列的最小值,如果指定列是字符串的类型,那么使用字符串的排列顺序运算;
sum():计算指定列的数值和,如果指定类型不是数值类型,那么计算结果为0;
avg():计算指列的平均值,如果指定列不是数值类型,那么计算结果为0
select count(*) from student;//如果一条记录中,所有列全为null则不计数
select count(*) from student where age>30;
select count(id) ,count(name) from student;//列id中有null不计数,列name中有null不计数
select sum(score) from student;
select max(score) from studnet;
select min(score) form student;
select avg(score) from student;
select count(name) as ZONGRENSHU,sum(score) as ZONGFENSHU from student;
select sum(score+ifnull(age,0))from student;
分组查询:(select后面第一个是当前分组列例如sex,第二个必须是聚合函数)
select sex,count(*) from student group by sex;
select sex,count(*),max(score),min(score) from student group by sex;
select sex,count(*) from student where score>80 group by sex;
having语句:
select sex,sum(score) from student group by sex having sum(score)>200;//查询总分大于200分的性别以及总分
查询每个部门中工资大于15000的人数且人数要大于2:
select deptno,count(*) from emp where sal>15000 group by deptno having count(*)>2;
注意:where是分组前条件,不参加分组
having是分组后条件
执行顺序和书写顺序:
select
from
where
group by
having
order by
limit语句:
select * from student limit 0,3;//查询三条记录从第0行开始
select * from studnet limtt 3,4;//查询四条记录从第三行开始
备份/恢复数据库:
导出数据库脚本:
mysqldump -u数据控用户名 -p数据库密码 要备份的数据库名 > 备份路径
mysqldump -uroot -pxxxxx aaaa>D:/a.sql
执行数据库脚本:
方式1:
mysql -u数据控用户名 -p数据库密码 要备份的数据库名 < 备份路径
mysql -uroot -pxxxxx aaaa<D:/a.sql
方式2:
source 之前备份好的数据库脚本文件
source D:/a.sql
例如:1.先备份数据库文件.sql文件 2.删除构该数据库在创建这个数据库3.切换到该数据库执行source D:/a.sql语句就恢复了数据库内容
完整性约束--主键:
列名 列类型(自增时为int) primary key [auto_increment],
create table student(
stu_id int primary key auto_increment,
stu_name varchar(30)
);
完整性约束--外键:
dno int,/该表要自己有这一列,一般和要关联的表的那一列相同
//constraint 外键名 foreign key (关联本表的那一列) references 关联的表表名(关联的表的那一列)
create table student(
stu_id int primary key auto_increment,
stu_name varchar(30)
);
注意:
1.constraint(约束);references(引用);
2.外键名的命名规则是:fk_本表名_关联表名
一对多关系:
例如:
create table hasband(
hid int primary key auto_increment,
hname varchar(50)
);
create table table wife(
wid int primary key auto_increment,
wname varchar(50),
hid int, -- 可以重复出现
constraint fk_wife_hasband foreign key(hid) references hasband(hid)
);
//利用本表的普通键作为外键引用外表主键,可以达到一对多的效果(多夫一妻)
一对一关系:
外键特点:非空、唯一、可引用hid
例如:
create table hasband(
hid int primary key auto_increment,
hname varchar(50)
);
create table table wife(
wid int primary key auto_increment,
wname varchar(50),
constraint fk_wife_hasband foreign key(wid) references hasband(hid)
);
//利用本表的主键作为外键,可以达到一对一的效果(一夫一妻)
多对多关系:
例如:
create table student(
sid int primary key auto_increment,
sname varchar(30)
);
create table teacher(
tid int primary key auto_increment,
tname varchar(30)
);
-- 关系关联表(中间表)
create table stu_tea(
sid int,
tid int,
constraint fk_student foreign key(sid) references student(sid),
constraint fk_teacher foreign key(tid) references
teacher(tid)
);
insert into student values(null,'zhangsan');
insert into student values(null,'lisi');
insert into student values(null,'wangwu');
insert into student values(null,'zhaoliu');
insert into student values(null,'hulil');
insert into teacher values(null,'hahaha');
insert into teacher values(null,'heihei');
insert into teacher values(null,'hehehe');
-- 加入关系表
-- 1老师教过学生1、2、3、4
insert into stu_tea values(1,1);
insert into stu_tea values(2,1);
insert into stu_tea values(3,1);
insert into stu_tea values(4,1);
-- 2老师教过2、4
insert into stu_tea values(2,2);
insert into stu_tea values(4,2);
-- 3老师教过2、4、5
insert into stu_tea values(2,3);
insert into stu_tea values(4,3);
insert into stu_tea values(5,3);
-- 2、4学生被1、2、3老师都教过——多对多关系
多表查询:
1. 合并结果集
** 要求两个"结果集"(并非两个表)的列数、列类型完全相同
create table ab (a int ,b varchar(20)) ;
create table cd (c int ,d varchar(20)) ;
select * from ab union all select * from ba;-- 不去重复行
select * from ab union select * from ba; -- 去重复行
2. 连接查询(涉及多表查询,第一步想到的就是用主外键去笛卡尔积)
** 内连接
** 方言样式:SELECT * FROM 表1 别名1, 表2 别名2 WHERE 别名1.xx=别名2.xx
例:
select e.ename,e.sal,d.dname
from emp e,dept d
where e.deptno=d.deptno;
** 标准样式:SELECT * FROM 表1 别名1 INNER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
例:
select e.ename,e.sal,d.dname
from emp e inner join dept d
on e.deptno=d.deptno;
(方言的逗号变inner join,where变on)
** 外连接
外连接有一主一次,左外就是左表为主
** 左外:SELECT * FROM 表1 别名1 LEFT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
例:
select e.ename,e.sal,d.dname
from emp e left outer join dept d
on e.deptno=d.deptno;
// emp表为主,那么主表中所有的记录无论满足不满足条件,都打印出来,当不满足条件时,右表要打印的全部使用null来补位
select e.name,e.sal,ifnull(d.dname,'无部门') as dname
from emp e left join dept d
on e.deptno=d.deptno; -- 人性化显示再起个别名
** 右外:SELECT * FROM 表1 别名1 RIGHT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
例如:
select e.ename,e.sal,d.dname
from emp e right outer join dept d
on e.deptno=d.deptno;
// dept表为主,那么主表中的所有记录无论满足不满足条件,都打印出来,当不满足条件时,左表要打印的全部使用null来补位
** 全连接:就是把左外和右外进行合并结果集就OK了
可以使用UNION来完成全链接
子查询:查询中有查询
例如:查工资最高的人的信息(where后)
select max(sal) from emp;-- 最高工资是多少
select * from emp where (select max(sal) from emp);
例如:查部门为'30'的人的信息(from后)
select * from emp where deptno=30;-- 查询部门为30的人
select t.empno,t.name from (select * from emp where deptno=30) t;-- 给这个虚表起个名字
1. 出现的位置:
* where后作为条件存在
* from后作为表存在(多行多列)
2. 条件
* (***)单行单列:SELECT * FROM 表1 别名1 WHERE 列1 [=、>、<、>=、<=、!=] (SELECT 列 FROM 表2 别名2 WHERE 条件)
* (**)多行单列:SELECT * FROM 表1 别名1 WHERE 列1 [IN, ALL, ANY] (SELECT 列 FROM 表2 别名2 WHERE 条件)
* (*)单行多列:SELECT * FROM 表1 别名1 WHERE (列1,列2) IN (SELECT 列1, 列2 FROM 表2 别名2 WHERE 条件)
* (***)多行多列:SELECT * FROM 表1 别名1 , (SELECT ....) 别名2 WHERE 条件
例题:
1. 查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。
分析:
列:d.deptno,d.dname,d.dloc,部门人数
表:dept d,emp e
条件:e.deptno=deptno(去笛卡尔积)
select * from dept;//d.deptno,d.dname,d.dloc
select deptno,count(*) from emp group by deptno;//部门人数,作为子查询
答案:
select d.*,z.cnt
from dept d inner join(select deptno,count(*) cnt from emp group by deptno) z
on d.deptno=z.deptno;
3. 列出所有员工的姓名及其直接上级的姓名。
分析:
列:员工姓名、上级姓名
表:emp e,emp m
条件:e.mgr=m.empno(员工的上级编号等于员工编号即为直接上级关系)
select *
from emp e left outer join emp m
on e.mgr=m.empno;//此时以null补位
答案:
select e.ename,ifnull(m.ename,'BOSS')
from emp e left outer join emp m
on e.mgr=m.empno;//此时以null补位
4. 列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称。
分析:
列:e.empno,e.ename,d.dname
表:emp e,dept d,dept d
条件:e.hiredate<m.hiredate
首先不查部门名称,只查部门编号!
列:e.empno,e.ename,d.deptno
表:emp e,dept d
条件:e.mgr=m.empno and e.hiredate<m.hiredate
select e.empno,e.ename,e.deptno,e.hiredate,m.ename,m.hiredate,d.deptno
from emp e,emp m
where e.mgr=m.empno and e.hiredate<m.hiredate
再把部门编号变成部门名称就需要用到dept表:(仍然要记得去除笛卡尔积)
答案:
select e.empno,e.ename,d.deptno,e.hiredate,m.ename,m.hiredate,d.deptn
from emp e,emp m,dept d
where e.mgr=m.empno and e.hiredate<m.hiredate and d.deptno=e.deptno
条件解析:
e.mgr=m.empno:员工的上级编号等于员工编号即为直接上级关系
e.hiredate<m.hiredate:入职时间早
d.deptno=e.deptno:对应的部门名称
5. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
分析:
列:*
表:emp e , dept d
条件:e.deptno=d.deptno
答案:
select *
from emp e right outer join dept d
where e.deptno=d.deptno
7. 列出最低薪金大于15000的各种工作及从事此工作的员工人数。
分析:
列:job,count(*)
表:emp e
条件:min(sal)>15000
分组:job
答案:
select job,count(*)
from emp e
group by job
having min(sal)>15000
8. 列出在销售部工作的员工的姓名,假定不知道销售部的部门编号。
分析:
列:e.ename
表:emo
条件:e.deptno=(通过dname查询出deptno)
答案:
select e.ename
from emp
whhere e.deptno=(select deptno from dept where dname='销售部');
*****四张表带一个子查询
9.列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级。
(salgrade表示工资的登记表,列有:工资等级(int)、最低工资、最高工资三列)
分析:
列:*
表:emp e
条件:sal>(查询出公司的平均工资)
select e.* ,d.dname,m.ename,s.grade
from emp e,dept d,emp m,salgrade s
where e.sal>(select avg(sal) from emp) and e.deptno=d.deptno and e.mgr=m.empno and e.sal between s.losal and s.hisal;
条件分析:
e.deptno=d.deptno :去笛卡尔积,部门
e.mgr=m.empno:直接上级关系
e.sal between s.losal and s.hisal:工资等级
答案:
select e.* ,d.dname,m.ename,s.grade
from emp e left outer join dept d on e.deptno=d.deptno
left outer join emp m on e.mgr=m.empno
left outer join salgrade s on e.sal between s.losal and s.hisal
where e.sal>(select avg(sal) from emp);
10.列出与庞统从事相同工作的所有员工及部门名称。
分析:
列:emp.*,dept.dname
表:emp e,dept d
条件:e.job=(查询出庞统的工作名)
答案:(不要忘了去笛卡尔积)
select e.*,d.danme
from emp e,dept d
where e.deptno=d.deptno and job=(select job from emp where ename='庞统');
*****
13.查出年份、利润、年度增长比
答案:
select y1.*,ifnull(concat((y1.zz-y2.zz)/y2.zz*100,'%'),'0%') 增长比
from tb_year y1 left outer join tb_year y2
on y1.year=y2.year+1;