MySql笔记:
1.测试mysql是否安装成功的dos命令:
mysql -uroot -pzhc
2.查看mysql的版本号:
未登录mysql之前:mysql --version/-V
登录mysql之后:select version();
3.mysql用户登录:
mysql -uroot -p
4.查看数据库:
show databases;
5.使用数据库:
use 数据库名称;
6.查看数据库的表:
show tables;
7.查看当前表所在的数据库:
select database();
8.从当前表查看另一个数据库的表:
show tables from 数据库名;
9.退出数据库exit/Ctri+c
10.创建数据库:
create database 数据库名称;
11.sql分类:
DQL语句 数据查询语言 select
DML语句 数据操作语言 insert delete update
DDL语句 数据库定义语言 create drop alter
TCL语句 事务控制语言 commit rollback
12.导入数据库脚本:
source **.sql
13.查看表的详细信息:
desc 表名;
14.查询单个字段:
select 字段名 from 表名;
15.查询多个字段:
select 字段1,字段2,...,from 表名;
16.查询全部字段:
select * from 表名;
17.给字段起别名(任意起的名字):
select 字段 as 别名字段 from 表名;
18.各种运算符查询:
= select 字段1,字段2 from 表名 where 字段1 =?;
<>/!= select 字段1,字段2, from 表名 where 字段1 <>/!=?;
不等号既能比较数字也能比较字符串。
> >= < <= select 字段1,字段2 from 表名 where 字段1 > / >= / < /<= ?;
and select 字段1,字段2 from 表名 where 字段1 >? and 字段1 ;
between...and select 字段1,字段2 from 表名 where 字段1 between ? and ?;
19.and 的优先级高于 or
select 字段1,字段2,字段3 from 表名 where 字段1 >? and (字段2=? or 字段2=?);
20.is / is not
select 字段1,字段2 from 表名 where 字段1 is / is not ?;
21.like 模糊查询
select 字段1,字段2 from 表名 where 字段1 like '%?%';
select 字段1,字段2 from 表名 where 字段1 like '?%';(以?开头)
select 字段1,字段2 from 表名 where 字段1 like '_?%';(第二个字母是?)
select 字段1,字段2 from 表名 where 字段1 like '%?_';(倒数第二个字母是?)
22.数据排序 asc desc:
单一字段排序 order by
select 字段1,字段2 from 表名 order by 字段1/字段1 asc;
select 字段1,字段2 from 表名 order by 字段1 desc;
select 字段1,字段2 from 表名 where 字段1=? order by 字段2 desc;
21.数据处理函数
单行处理函数:
转换大小写:
select lower/upper(字段) as 别名字段 from 表名;
substr:
substr(被截取的字符串/字段,起始下标,截取的长度)
select substr(字段,1,2) as 别名字段 from 表名;
length:
select length(字段) as 别名字段 from 表名;
trim(去掉字符串前后的空格):
select * from 表名 where 字段名 = trim('字符串');
round(四舍五入):
select round(数字,保留几位小数);
例:select round(112.23,1);
rand(随机数):
0~1 select rand();
case ? when ? then ? else ? end:
例:匹配工作岗位,当为manager时,薪水上调10%,当为salesman时,薪水上调50%,其他岗位薪水不变
select job,ename,
(case job
when 'manager' then sal*1.1
when 'salsman' then sal*1.5
else sal
end) as newsal from emp;
-- ifnull:
ifnull(expr1,expr2)
假如expr1不为NULL,则IFNULL()的返回值为expr1; 否则其返回值为expr2。IFNULL()的返回值是数字或是字符串,具体情况取决于其所使用的语境。
mysql>SELECT IFNULL(1,0);
->1
mysql>SELECT IFNULL(NULL,10);
->10
mysql>SELECT IFNULL(1/0,10);
->10
mysql>SELECT IFNULL(1/0,'yes');
->'yes'
select 字段1,(字段2+ifnull(字段3,0)) as 别名字段 from 表名;
-- str_to_date:
select 字段1,字段2 from 表名 where 字段1 = str_to_date('?','?');
例: select nane,birthdate from emp where birthdate = str_to_date('12-03-1996','%m-%d-%Y');
data_format(将‘日期类型’ 转换为特定格式的‘日期字符串’类型):
date_format(字段,'日期格式');
例:select date_format(birthdate,'%m-%d-%Y' / '%m%d%Y' / '%m/%d/%Y') as mydate from birth;
多行处理函数(会自动忽略null):
sum(字段):求某一列的和,null会自动被忽略.
select sum(字段) as 别名字段 from 表名;
avg(字段):求某一列的平均值,null会自动被忽略.
select avg(字段) as 别名字段 from 表名;
max(字段)/min(字段):
select max(字段)/min(字段) as 别名字段 from 表名;
count取得记录数:
select count(字段) as 别名字段 from 表名;
select count(*) as 别名字段 from 表名 where 字段 ?;
distinct(将查询结果中某一字段的重复记录去除掉):
distinct 字段名 / distinct 字段名1,字段名2
distinct 字段名A :去除与字段名A相同的记录
distinct 字段名A,字段名B:去除与字段名A和字段名B同时相同的记录
例:select distinct job from emp;
select distinct name,job from emp;
-- group by(分组查询):
-- group by 字段名;
select 类别, sum(数量) as 数量之和
from A
group by 类别
例: select
job,max(sal) as maxsal
from
emp
group by
job;
-- having(如果想对分组的数据再进行过滤,需要使用having),having必须与group by联合使用:
例: select
job,avg(sal) as avgsal
from
emp
group by
job
having
avgsal>2000;
数据过滤可以用where、having:他们之间的区别是where用在group by之前,having用在group by之后.
例: select
job,max(sal) as maxsal
from emp
where job <>'manager'
group by
job;
select语句总结:
一个完成的SQL语句如下:
select
xxxx
from
xxxx
where
xxxx
group by
xxxx
having
xxxx
order by
xxxx
以上关键字的顺序不能变,严格遵守
以上语句的执行顺序:
1) from 将硬盘上的表文件加载到内存
2) where 将符合条件的数据行摘取出来。生成一张新的临时表
3) group by 根据列中的数据种类,将当前临时表划分成若干个新的临时表
4) having 可以过滤掉group by生成的不符合条件的临时表
5) select 对当前临时表进行整列读取
6) order by 对select生成的临时表,进行重新排序,生成新的临时表
7) limit 对最终生成的临时表的数据行,进行截取.
22.跨表查询:
年代分类:
SQL92
例: select ename,dname from emp as e,dept as d where e.deptno=d.deptno;
SQL99(掌握)
语法结构:
select xxx from A表名 join B表名 on 表的连接条件;
例:
select
e.ename,d.dname
from
emp as e
join
dept as d
on
e.deptno=d.deptno
where
数据过滤条件;
连接方式分类:
内连接: 省略了一个关键字:inner
等值连接
例:查询出员工所对应的部门名称
select
e.ename,d.dname
from
emp as e
inner join
dept as d
on
e.deptno=d.deptno
非等值连接
例: 查询出员工薪水所对应的薪水等级:显示员工名称,薪水,薪水等级
select
e.ename,e.sal,s.grade
from
emp as e
inner join
salgrade as s
on
e.sal between s.losal and s.hisal;
自连接
把一张表看成两张表使用
例: 查询出员工所对应的领导名称:显示员工名称和领导名称
select
a.ename,b.ename
from
emp as a
join
emp as b
on
a.mgr=b.empno;
外连接
省略了一个关键字:outer
定义: A表和B表能够完全匹配的记录查询出来之外,将其中一张表的记录无条件的完全查询出来,对方没有匹配的
记录时,会自动模拟出null值与之匹配;
-- 左外连接/左连接
-- 左连接即:返回左边表中所有被查询字段+右边表中符合条件的字段。
例:
select
a.ename,b.ename as leadername
from
emp as a
left outer join
emp as b
on
a.mgr=b.empno;
-- 右外连接/右连接
-- 右连接即:返回右边表中所有被查询字段+左边表中符合条件的字段。
例:
select
e.ename,d.dname
from
emp as e
right outer join
dept as d
on
e.deptno=d.deptno;
全连接
-- 多张表进行表连接的语法格式:
select
xxx
from
A表
join
B表
on
连接条件1
join
C表
on
连接条件2;
原理:A表和B表通过连接条件1连接之后,A表再和C表通过连接条件2进行连接;
例:
表: emp,dept,salgrade
select
d.dname,
e.ename,
b.ename as leadername,
s.grade
from
emp e
join
dept d
on
e.deptno=d.deptno
join
emp b
on
e.mgr=b.empno
join
salgrade s
on
e.sal between s.losal and s.hisal;
23.子查询:
定义:select语句嵌套select语句被称为子查询;
注意:select子句可出现在select、from、where关键字后面,如下:
select...(select)...[很少使用]
from...(select)...
where...(select)...
where...(select)...
例: 找出薪水比公司平均薪水高的员工,要求显示员工名和薪水
select ename,sal from emp where sal>(select avg(sal) as avgsal from emp);
from...(select)...
例:找出每个部门的平均薪水,并且要求显示平均薪水的薪水等级
第一步:先求出每个部门的平均薪水
select
e.deptno,avg(e.sal) as avgsa
from
emp e
group by
e.deptno;
将以上查询结果当成临时表t[deptno,avgsal]
select
t.avgsal,s.grade
from
(select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno)t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
24.union合并查询结果集:
例: 查询出岗位为manager和salesman的员工
select ename,job from emp where job='manager' or job='salesman';
select ename,job from emp where job in ('manager','saleman');
union 合并相加结果集
select ename,job from emp where job='manager'
union
select ename,job from emp where job='salesman';
25.limit(只在MySQL中起作用)获取一表前几条或中间几行数据;
用法:
limit起始下标m,长度n
m:记录开始的index,默认从0开始,表示第一条记录;
n:指从第m+1条开始,取n条;
例: 取前五个员工的信息:
select * from emp limit 0,5;
select * from emp limit 5;
例: 取员工薪水的前五名:
select ename,sal from emp order by sal desc limit 5;
例: 取员工薪水的5——8名:
select ename,sal from emp order by sal desc limit 4,4;
26.-- limit实现分页:
页码: pageNo pageSize
第1页 1,2,3 limit 0,3
第2页 4,5,6 limit 3,3
第3页 7,8,9 limit 6,3
第*页 *,*,* limit (pageNO-1)*pageSize,pageSize
27.-- 创建表的语法:
create table t_表名/tbl_表名(
字段名称 字段类型 字段长度 字段约束,
字段名称 字段类型 字段长度 字段约束,
字段名称 字段类型 字段长度 字段约束,
字段名称 字段类型 字段长度 字段约束,
字段名称 字段类型 字段长度 字段约束
);
28.-- 删除表的语法:
drop table if exists 表名;(这样删除表,即使表不存在也不会报错)
29.查看创建表时的语法:
show create table 表名;
30.复制一张表的语法:
create table 表名 as 查询语句;
例:create table emp_bak as select * from emp;
31.DML语法: insert update delete
-- insert 语法:
insert into 表名 (字段名,字段名,字段名,字段名) values (字段值,字段值,字段值,字段值);
例:insert into t_student (no,name,gender,birth,email) values (1,'zhangsan','1',str_to_date('1999-10-10','%Y-%m-%d'),'
[email protected]');
insert into t_student (no,name,gender) values (4,'lilei','1');
32.查看表中的数据:
select * from 表名;
33.update 语法:
update 表名 set 字段名称=字段值,字段名称=字段值 where 限制条件;
例:update t_student set birth=str_to_date('1995-10-20','%Y-%m-%d') where no=4;
34.delete 语法:
delete from 表名;(删除表中所有的数据)
delete from 表名 where 限制条件;
35.字符集编码问题:
查看数据库的各个字符集编码:
show variables like '%char%';
修改字符集编码:
例:set character_set_results =gbk;
36.快速向表中插入数据:
insert into 表名 select 字段名,字段名,字段名 from 表名 where 限制条件;
例:create table emp_bak as select empno,ename,job from emp where job='manager';
insert into emp_bak select empno,ename,job from emp where job='manager';
37.-- 修改表的结构:
alter
-- 添加一个字段:
alter table t_student add email varchar(128);
-- 修改字段的大小:
alter table t_student modify no int(8);
-- 删除一个字段:
alter table t_student drop email;
-- 改变字段名:
alter table t_student change name username varchar(32);
38.-- 约束(constraint)
作用: not null约束的字段不能为null值,必须赋具体数据;
39.-- 唯一性约束(unique)
作用:unique约束的字段具有唯一性,不可重复
注意:‘unique约束’约束的字段不能重复,但是可以为null,null不是一个值,也不能用等号比较;
分为列级约束和表级约束:
-- 列级约束:
email varchar(128) unique
例:drop table if exists t_user;
create table t_user(
id int(10),
name varchar(32) not null,
email varchar(128) unique
);
-- 表级约束:
unique(email)
例:-- 创建表
create table t_user(
id int(4),
name varchar(32) not null,
email varchar(128),
constraint t_user_name_email_unique unique(name,email)
);
40.-- 非空约束与唯一性约束联合使用
例:
DROP TABLE if EXISTS t_user;
CREATE TABLE t_user(
id INT(4),
name VARCHAR(32) NOT NULL UNIQUE
);
INSERT INTO t_user (id,NAME) VALUES (1,'lisi');
SELECT * FROM t_user;
-- INSERT INTO t_user (id,NAME) VALUES (2,'lisi');
-- INSERT INTO t_user (id) VALUES (3);
41.-- 主键约束
主键约束 primary key 简称PK
主键涉及到三个术语:主键约束、主键字段、主键值,他们之间的关系是:
表中的某个字段添加主键约束之后,该字段被称为主键字段,主键字段中出现的每一个数据都被称为主键值.
-- 主键的作用:
1) 添加主键primary key的字段既不能重复也不能为空,效果与'not null unique'相同,
但本质是不同的,添加主键约束之后,主键不仅会有'not null unique'作用,而且主键字段还会自动添加
’索引——index’;
2) 一张表应该有主键,若没有,表示这张表是无效的."主键值"是当前行数据的唯一标识,
是当前行数据的身份证号(即使表中两行数据完全相同,但是由于主键不同,我们也认为这是两行完全不同的数据).
-- 主键根据个数分类:单一主键、复合主键
-- 表中主键个数
无论是单一主键还是复合主键,一张表中主键约束只能有一个.
单一主键是给一个字段添加主键约束;
列级约束: id int(10) primary key
例:
CREATE TABLE t_user(
id INT(4) PRIMARY KEY,
NAME VARCHAR(32) NOT NULL
);
表级约束:
CREATE TABLE t_user(
id INT(4) ,
NAME VARCHAR(32) NOT NULL,
PRIMARY KEY(id)
);
-- 复合主键
CREATE TABLE t_user(
id INT(4) ,
NAME VARCHAR(32) NOT NULL,
constraint t_user_id_name_PK PRIMARY KEY(id,NAME)
);
-- 主键根据性质分类:
自然主键和业务主键
1) 自然主键:主键值若是一个自然数,并且这个自然数与业务没有任何关系,这种主
键称为自然主键;
2) 业务主键:主键值若和当前表中的业务紧密相关,那么这种主键值被业务主键;如果业务
发生改变时,业务主键往往会受到影响,所以业务主键使用较少,大多情况使用自然主键.
-- 自动生成主键值
auto_increment
例:
CREATE TABLE t_user(
id INT(4) PRIMARY KEY auto_increment,
NAME VARCHAR(32) NOT NULL
);
INSERT INTO t_user (NAME) VALUES ('xiaoming');
42. -- 外键约束
外键约束 foreign key 简称:FK
外键涉及到的术语:外键约束、外键字段、外键值,三者之间的关系是:
给某个字段添加外键约束之后,该字段称为外键字段,外键字段中的数据称为外键值;
外键根据个数分为:单一外键、复合外键
1) 单一外键: 给一个字段添加外键约束
2) 复合外键: 给多个字段联合添加一个外键
外键在同一张表中可以有多个外键存在
例:
DROP TABLE IF EXISTS t_student;
DROP TABLE IF EXISTS t_class;
CREATE TABLE t_class(
cno INT(4) PRIMARY KEY,
cname VARCHAR(32)
);
CREATE TABLE t_student(
sno INT(4) PRIMARY KEY auto_increment,
sname VARCHAR(32),
classno INT(4),
CONSTRAINT t_student_classno_fk FOREIGN KEY (classno) REFERENCES t_class(cno)
);
INSERT INTO t_class (cno,cname) VALUES (100,'高三1班');
INSERT INTO t_class (cno,cname) VALUES (200,'高三2班');
INSERT INTO t_class (cno,cname) VALUES (300,'高三3班');
INSERT INTO t_student (sname,classno) VALUES ('张三',100);
INSERT into t_student (sname,classno) VALUES ('李四',200);
要注意以下三点:
1.外键字段可以为null,外键为空的数据也叫孤儿数据
2.被引用字段必须具有unique约束
3.有了外键引用之后,表分为父表和子表,以上父表: 班级表t_class ;
子表是:学生表 t_student;
创建表时先创建父表,再创建子表;
插入数据时,先插入父表数据再插入子表数据;
在一对多的情况下,在多的那个表下面添加外键
-- 查询出学生所对应的班级名称
SELECT
s.sname,c.cname
FROM
t_student s
JOIN
t_class c
ON
s.classno=c.cno;
-- 级联更新与级联删除
用法:在添加级联更新与级联删除的时候,需要在外键约束后面添加关键字;
注意:级联更新与级联删除操作谨慎使用,因为级联操作会将数据改变或者删除
-- 级联删除
on delete cascade
-- 级联更新
on update cascade
定义:在删除父表数据的时候,级联删除子表中的数据;
1) 删除外键约束
语法: alter table 表名 drop foreign key 外键字段;
2) 再进行级联删除或者级联更新
例:级联删除
ALTER TABLE t_student DROP FOREIGN KEY t_student_classno_fk;
ALTER TABLE t_student ADD CONSTRAINT t_student_classno_fk FOREIGN KEY (classno)
REFERENCES t_class(cno) ON DELETE CASCADE;
例:级联更新
ALTER TABLE t_student DROP FOREIGN KEY t_student_classno_fk;
ALTER TABLE t_student ADD CONSTRAINT t_student_classno_fk FOREIGN KEY (classno)
REFERENCES t_class (cno) ON UPDATE CASCADE;
-- 常用的存储引擎
InnoDB存储引擎
InnoDB存储引擎是MySQL数据库的默认引擎:
它管理的表具有以下特征:
1) 每个InnoDB表在数据库目录中以.frm格式文件表示
2) InnoDB表空间tablespace被用于储存表的内容
3) 提供一组用来记录事务性活动的日志文件
4) 用commmit(提交)、savepoint及rollback(回滚)支持事务处理
5) 提交全部ACID兼容
6) 在MySQL服务器崩溃后提供自动恢复
7) 多版本(MVCC)和行级锁定
8) 支持外键引用的完整性,包括级联更新和删除
-- 选择合适的存储引擎
1) MyISAM表最适合于大量的数据读而少量数据更新的混合操作.MyISAM表的另一种适用情形是使用压缩的只读表.
2) 如果查询中包含较多的数据更新操作,应使用InnoDB.其行级锁机制和多版本的支持为数据读取和更新的混合提
供了良好的并发机制.
3) 使用MEMORY存储引擎存储非永久需要的数据,或者是能够从基于磁盘的表中重新生成的数据.
-- 索引
什么情况下适合给表中字段添加索引
1) 该字段数据量庞大
2) 该字段很少的DML操作(由于索引也需要维护,DML操作多的话,也影响检索效率)
3) 该字段经常出现在where条件中
注意:实际开发中会根据项目需求或客户需求等综合因素来做调整
-- 创建索引
1) create index 索引名 on 表名 (列名)
2) create unique index 索引名 on 表名 (列名)
注意:添加 unique表示在该表中的该列添加一个唯一性约束
例: create index dept_dname_index on dept(dname);
-- 查看索引
1) show index from 表名
例:show index from dept;
-- 删除索引
1) drop index 索引名 on 表名
例: drop index dept_dname_index on dept;
-- 视图
什么是视图:
1) 视图对应英文单词:view
2) 视图在数据库管理系统中也是一个对象,也是以文件形式存在的
3) 视图也对应了一个查询结果,只是从不同的角度查看数据
-- 创建视图
create view 视图名称 as 查询语句;
例: create view myview as select * from emp;
-- 查看视图
show tables;
-- 删除视图
DROP VIEW IF EXISTS myview;
43. -- 数据库设计三范式
意思是:设计数据库的时候所依据的规范,共有三个规范
-- 第一范式:主键、字段不能再分
定义:要求有主键,数据库中不能出现重复记录,每一个字段是原子性不能再分
注意:1.每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求
2.主键主要通常采用数值型或定长字符串表示
3.关于列不可再分,应根据具体的情况来决定
-- 第二范式:非主键字段完全依赖主键
定义:第二范式是建立在第一范式基础之上,要求数据库中所有非主键字段完全依赖主键,
不能产生部分依赖(严格意义上说:尽量不要使用联合主键)
结论:典型的"多对多"的设计
-- 第三范式
定义:建立在第二范式基础之上,要求非主键字段不能产生传递依赖于主键字段;
结论:典型的一对多
在多的一方添加外键
43.-- 事务Transaction
什么是事务:
1) 一个最小的不可再分的工作单元
2) 通常一个事务对应一个完整的业务;(如:银行转账业务)
3) 而一个完整的业务需要批量的DML(insert、update、delete)语句共同完成;
4) 事务只和DML语句有关系,或者说只有DML语句才有事务
以上所描述的批量DML语句共有多少DML语句,这个和业务逻辑有关系,业务逻辑不同DML语句个数不同;
-- 事务的四个特征:
1) 原子性(Atomicity)
a) 事务是最小单元,不可再分
2) 一致性(Consistency)
a) 事务要求所有的DML语句操作的时候,必须保证同时成功或同时失败;
3) 隔离性(Isolation)
a) 一个事务不会影响其他事物的运行
4) 持久性(Durability)
a) 在事务完成之后,该事务对数据库所作的更改将持久地保存在数据库中,并不会被回滚
-- 事务中的一些概念
1) 开启事务:start transaction
2) 结束事务: end transaction
3) 提交事务:commit transaction
4) 回滚事务:rollback transaction
-- 和事务有关的两条SQL语句
1) commit 提交
2) rollback 回滚
-- 事务开启和结束的标志
开启的标志
1) 任何一条DML语句执行,标志事务的开启
结束的标志
1) 提交(commit)或者(rollback)
a) 提交:成功的结束,将所有的DML语句操作记录和底层硬盘文件中数据进行一次同步
b) 回滚:失败的结束,将所有DML语句操作记录全部清空
-- 重点
1) 在事务进行过程中,未结束之前,DML语句是不会修改底层数据库文件中的数据
2) 只是将历史操作记录一下,在内存中完成记录
3) 只有在事务结束的,而且是成功结束的时候才会修改底层硬盘文件中的数据
-- 查看MySQL默认事务
show variables like '%commit%';
1) 在MySQL数据库管理系统中,默认情况下,事务是自动提交的;也就是说,只要执行一条DML语句,就开启了事务,并且提交了事务
第一种:关闭MySQL事务自动提交
1) 事务成功用法: start transaction; commit;
第一步:start transaction; 手动开启事务
第二步:DML语句.... 执行批量DML语句
第三步:commit 手动提交事务【事务成功结束】
-- 事务的隔离级别
隔离性有四个隔离级别:
1) read uncommitted 读未提交
2) read committed 读已提交
3) repeatable read 可重复读
4) serializable 串行化
read committed 读未提交(级别最低)
1) 事务A和事务B,事务A未提交的数据,事务B可以读取
2) 这里读取到的数据可以叫做 "脏数据" 或 "脏读 Dirty Read"
3) 读未提交隔离级别最低,这种级别一般只在理论上存在,数据库默认隔离级别一般都高于该隔离级别;
-- 查看隔离级别
1) 查看当前会话级隔离级别
select @@tx_isolation;
select @@session.tx_isolation;
2) 查看当前全局隔离级别:@@global.tx_isolation;
-- 设置服务器默认隔离级别
1) 第一种:修改my.ini配置文件
在my.ini文件中的[mysqld]下面添加:
--------------------my.ini------------------------
[mysqld]
transaction-isolation=READ-COMMITTED
------------------my.ini--------------------------
a) 隔离级别可选项为:
-- READ-UNCOMMITTED
-- READ-COMMITTED
-- REPEATABLE-READ
-- SERIALIZABLE
2) 第二种:通过命令方式设置事务隔离级别
a) set transaction isolation level isolation-level;
b) isolation-level 可选值:
-- READ UNCOMMITTED
-- READ COMMITTED
-- REPEATABLE READ
-- SERIALIZABLE
-- 设置隔离级别作用的范围
1) 事务隔离级别的作用范围分为两种:会话级、全局级
a) 会话级(session) : 只对当前会话有效
b) 全局级(global) : 对所有会话有效
1. -- 取得每个部门最高薪水的人员名称
第一步:取得每个部门的最高薪水,按照部门分组求最大值
select
e.deptno,max(e.sal) as maxsal
from
emp e
group by
e.deptno;
第二步:将上面的查询结果当做临时t(deptno,maxsal)与emp e进行表连接,表连接条件t.deptno=e.deptno,数据过滤条件:t.maxsal=e.sal
select
e.deptno,e.ename,t.maxsal,e.sal
from
(select
e.deptno,max(e.sal) as maxsal
from
emp e
group by
e.deptno)t
join
emp e
on
t.deptno=e.deptno
where
t.maxsal=e.sal
order by
e.deptno;
2. -- 哪些人的薪水在部门平均薪水之上
第一步:求出每个部门的平均薪水
select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno;
将以上查询结果当成临时表t(deptno,avgsal)
select
t.deptno,e.ename
from
(select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno=t.deptno)t
join
emp e
on
e.deptno=t.deptno
where
e.sal>t.avgsal;
3. -- 取得部门中(所有人的)平均薪水等级
3.1 -- 取得部门中所有人的平均薪水的,等级
第一步:求出部门的平均薪水
将以下查询结果当成临时表t(deptno,avgsal)
select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno;
-- 查看薪水等级表
select * from salgrade;
select
t.deptno,t.avgsal,s.grade
from
(select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno)t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
3.2 -- 取得部门中所有人的平均的薪水等级
第一步:求出每个人的薪水等级
select
e.deptno,e.ename,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal
order by
e.deptno;
将以上查询结果当成临时表t(deptno,ename,grade)
select
t.deptno,avg(t.grade) as avgGrade
from
(select
e.deptno,e.ename,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal) t
group by
t.deptno;
4.-- 不用组函数(MAX),取得最高薪水(给出两种解决方案)
1) select sal from emp order by sal desc limit 1;
2) select
distinct a.sal
from
emp a
join
emp b
on
a.sal < b.sal;
select sal from emp where sal not in (select
distinct a.sal
from
emp a
join
emp b
on
a.sal < b.sal );
5. -- 取得平均薪水最高的部门的部门编号
第一步:求出部门平均薪水
select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno;
第二步:将以上查询结果当成临时表t(deptno,avgsal)
select max(t.avgsal) as maxAvgSal from (select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno) t;
select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno
having
avgsal = (select max(t.avgsal) as maxAvgSal from (select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno) t);
-- having和where的区别
1) having一般跟在group by之后,执行记录组选择的一部分来工作的。
2) 再者having可以用聚合函数,如having sum(qty)>1000
3) HAVING子句必须位于GROUP BY之后ORDER BY之前。
6. -- 取得平均薪水最高的部门的部门名称
select
e.deptno,d.dname,avg(e.sal) as avgsal
from
emp e
join
dept d
on
e.deptno = d.deptno
group by
e.deptno,d.dname
having
avgsal = (select max(t.avgsal) as maxAvgSal from (select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno) t);
7. -- 求平均薪水的等级最低的部门的部门名称
第一步: 部门的平均薪水
select
e.deptno,avg(e.sal) as avgsal
from
emp e
group by
e.deptno;
第二步:将以上结果当成临时表t(deptno,avgsal)与salgrade表进行表连接:
t.avgsal between s.losal and s.hisal;
select
t.deptno,t.dname,s.grade
from
(select
e.deptno,d.dname,avg(e.sal) as avgsal
from
emp e
join
dept d
on
e.deptno = d.deptno
group by
e.deptno,d.dname) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
将以上查询结果当成一张临时表t
select min(t.grade) as minGrade from (select
t.deptno,t.dname,s.grade
from
(select
e.deptno,d.dname,avg(e.sal) as avgsal
from
emp e
join
dept d
on
e.deptno = d.deptno
group by
e.deptno,d.dname) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal) t;
8. -- 取得比普通员工(员工代码没有在mgr上出现的)的最高薪水还要高的经理人姓名
第一步: 找出普通员工(员工代码没有出现在mgr上的)
1.1 先找出mgr有哪些人
select distinct mgr from emp;
select * from emp where empno in (select distinct mgr from emp);
select max(sal) as maxsal from emp where empno not in (select distinct mgr from emp where mgr is not null);
-- not in 不会自动忽略空值,in会自动忽略空值
select ename from emp where sal >(select max(sal) as maxsal from emp where empno not in (select distinct mgr from emp where mgr is not null));
9. -- 取得薪水最高的前五名员工
select * from emp order by sal desc limit 0,5;
10.-- 取得薪水最高的第六到第十名员工
select * from emp order by sal desc limit 5,5;
11. -- 取得最后入职的5名员工
select * from emp order by hiredate desc limit 5;
12. -- 取得每个薪水等级有多少员工
第一步:查询出每个员工的薪水等级
select
e.ename,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal
order by
s.grade;
将以上查询结果当成临时表t(ename,grade)
select
t.grade,count(t.ename) as totalEmp
from
(select
e.ename,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal) t
group by
t.grade;
13.
有三个表S(学生表),C(课程表),SC(学生选课表)
S (sno,sname) 代表 (学号,姓名)
C (cno,cname,cteacher) 代表 (课号,课名,教师)
SC (sno,cno,scgrade) 代表 (学号,课号,成绩)
问题:
1. 找出没选过"黎明"老师的所有学生姓名.
2. 列出2门以上 (含2门) 不及格学生姓名及平时成绩.
3. 即学过1号课程又学过2号课程所有学生的姓名.
CREATE TABLE s(
sno INT(4) PRIMARY KEY auto_increment,
sname VARCHAR(32)
);
INSERT INTO s(sname) VALUES ('zhangsan');
INSERT INTO s(sname) VALUES ('lisi');
INSERT INTO s(sname) VALUES ('wangwu');
INSERT INTO s(sname) VALUES ('zhaoliu');
CREATE TABLE c(
cno INT(4) PRIMARY KEY auto_increment,
cname VARCHAR(32),
cteacher VARCHAR(32)
);
INSERT INTO c(cname,cteacher) VALUES ('Java','吴老师');
INSERT INTO c(cname,cteacher) VALUES ('C++','王老师');
INSERT INTO c(cname,cteacher) VALUES ('C#','张老师');
INSERT INTO c(cname,cteacher) VALUES ('MySQL','郭老师');
INSERT INTO c(cname,cteacher) VALUES ('Oracle','黎明');
CREATE TABLE sc(
sno INT(4),
cno INT(4),
scgrade DOUBLE (3,1),
CONSTRAINT sc_sno_cno_pk PRIMARY KEY (sno,cno),
CONSTRAINT sc_sno_fk FOREIGN KEY (sno) REFERENCES s(sno),
CONSTRAINT sc_cno_fk FOREIGN KEY (cno) REFERENCES c(cno)
);
INSERT INTO sc(sno,cno,scgrade) VALUES (1,1,30);
INSERT INTO sc(sno,cno,scgrade) VALUES (1,2,50);
INSERT INTO sc(sno,cno,scgrade) VALUES (1,3,80);
INSERT INTO sc(sno,cno,scgrade) VALUES (1,4,90);
INSERT INTO sc(sno,cno,scgrade) VALUES (1,5,70);
INSERT INTO sc(sno,cno,scgrade) VALUES (2,2,80);
INSERT INTO sc(sno,cno,scgrade) VALUES (2,3,50);
INSERT INTO sc(sno,cno,scgrade) VALUES (2,4,70);
INSERT INTO sc(sno,cno,scgrade) VALUES (2,5,80);
INSERT INTO sc(sno,cno,scgrade) VALUES (3,1,60);
INSERT INTO sc(sno,cno,scgrade) VALUES (3,2,70);
INSERT INTO sc(sno,cno,scgrade) VALUES (3,3,80);
INSERT INTO sc(sno,cno,scgrade) VALUES (4,3,50);
INSERT INTO sc(sno,cno,scgrade) VALUES (4,4,80);
/*
1. 找出没选过“黎明”老师的所有学生姓名
2. 列出2门以上 (含2门) 不及格学生姓名及平均成绩
3. 即学过1号课程又学过2号课所有学生的姓名
*/
-- 先找出选过黎明老师的学生编号 --> 黎明老师的授课的编号
SELECT cno FROM c WHERE cteacher = '黎明';
SELECT sno FROM sc WHERE cno = (SELECT cno FROM c WHERE cteacher = '黎明');
SELECT * FROM s WHERE sno NOT in (SELECT sno FROM sc WHERE cno = (SELECT cno FROM c WHERE cteacher = '黎明'));
-- 列出2门以上 (含2门) 不及格学生姓名及平均成绩
t1
SELECT
sc.sno,s.sname,COUNT(*) AS studentNum
FROM
sc
JOIN
s
ON
sc.sno=s.sno
WHERE
scgrade < 60
GROUP BY
sc.sno,s.sname
HAVING
studentNum >= 2;
t2
SELECT
sc.sno,avg(sc.scgrade) AS avgscgrade
FROM
sc
GROUP BY
sc.sno;
SELECT
t1.sname,t2.avgscgrade
FROM
(SELECT
sc.sno,s.sname,COUNT(*) AS studentNum
FROM
sc
JOIN
s
ON
sc.sno=s.sno
WHERE
scgrade < 60
GROUP BY
sc.sno,s.sname
HAVING
studentNum >= 2
)t1
JOIN
(SELECT
sc.sno,avg(sc.scgrade) AS avgscgrade
FROM
sc
GROUP BY
sc.sno
)t2
ON
t1.sno=t2.sno;
-- 即学过1号课程又学过2号课程的所有学生的姓名
SELECT sno FROM sc WHERE cno=1;
SELECT sno FROM sc WHERE cno=2;
SELECT
s.sname
FROM
sc
JOIN
s
ON
sc.sno=s.sno
WHERE
cno=1 AND sc.sno in (SELECT sno FROM sc WHERE cno=2);
14. -- 列出所有员工及领导的名字
select
e.ename,
b.ename as leadername
from
emp e
left join
emp b
on
e.mgr=b.empno;
15. -- 列出受雇日期早于其直接上级的所有员工编号、姓名、部门名称
select
d.dname,
e.ename,
e.empno
from
emp e
join
emp b
on
e.mgr=b.empno
join
dept d
on
e.deptno=d.deptno
where
e.hiredate
16. -- 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
select
d.dname,
e.*
from
emp e
right join
dept d
on
e.deptno=d.deptno;
17. -- 列出至少有五个员工的所有部门
第一步:先求出每个部门的员工数量
select
e.deptno,count(e.ename) as totalEmp
from
emp e
group by
e.deptno;
select
e.deptno,count(e.ename) as totalEmp
from
emp e
group by
e.deptno
having
totalEmp >= 5;
18. -- 列出薪水比"SMITH"多的所有员工信息
select sal from emp where ename = 'SMITH';
select * from emp where sal > (select sal from emp where ename = 'SMITH');
19. -- 列出所有"CLKERK"(办事员)的姓名及其部门名称,部门人数
t1
select
d.deptno,d.dname,e.ename
from
emp e
join
dept d
on
e.deptno=d.deptno
where
e.job='CLKERK';
-- 求出每个部门的员工数量
t2
select
e.deptno,count(e.ename) as totalEmp
from
emp e
group by
e.deptno;
select
t1.deptno,t1.dname,t1.ename,t2.totalEmp
from
(select
d.deptno,d.dname,e.ename
from
emp e
join
dept d
on
e.deptno=d.deptno
where
e.job='CLKERK') t1
join
(select
e.deptno,count(e.ename) as totalEmp
from
emp e
group by
e.deptno) t2
on
t1.deptno=t2.deptno;
20. -- 列出最低薪水大于1500的各种工作及从事此工作的全部雇员人数
第一步: 先求出每种工作岗位的最低薪水
select
e.job,min(e.sal) as minsal
from
emp e
group by
e.job;
select
e.job,min(e.sal) as minsal,count(e.ename) as totalEmp
from
emp e
group by
e.job
having
minsal > 1500;
21. -- 列出在部门"SALES"<销售部>工作的员工的姓名,假定不知道销售部门的部门编号
select deptno from dept where dname = 'SALES';
select ename from emp where deptno=(select deptno from dept where dname = 'SALES');
22. -- 列出薪金高于公司平均薪金的所有员工,所在部门、上级领导、雇员的工资等级
第一步: 求出公司的平均薪水
select avg(sal) as avgsal from emp;
select
d.dname,
e.ename,
b.ename as leadername,
s.grade
from
emp e
join
dept d
on
e.deptno=d.deptno
left join
emp b
on
e.mgr=b.empno
join
salgrade s
on
e.sal between s.losal and s.hisal
where
e.sal > (select avg(sal) as avgsal from emp);
23. -- 列出与"SCOTT"从事相同工作的所有员工及部门名称
--查询出SCOTT的工作岗位
select job from emp where ename = 'SCOTT';
select
d.dname,
e.*
from
emp e
join
dept d
on
e.deptno=d.deptno
where
e.job=(select job from emp where ename = 'SCOTT');
24. -- 列出薪金等于部门30中员工的薪金的其他员工的姓名和薪金
select distinct sal from emp where deptno=30;
select ename,sal from emp where sal in (select distinct sal from emp where deptno=30) and deptno <> 30;
25. -- 列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称
第一步: 先找出部门30的最高薪水
select max(sal) as maxsal from emp where deptno = 30;
select
d.dname,
e.ename,
e.sal
from
emp e
join
dept d
on
e.deptno=d.deptno
where
e.sal > (select max(sal) as maxsal from emp where deptno = 30);
26. -- 列出在每个部门工作的员工数量、平均工资和服务期限
to_days(日期类型) --> 天数
获取数据库的系统当前时间的函数是: now()
select ename,(to_days(now())-to_days(hiredate))/365 as serveryear from emp;
select avg((to_days(now())-to_days(hiredate))/365) as avgserveryear from emp;
select
e.deptno,
count(e.ename) as totalEmp,
avg(e.sal) as avgsal,
avg((to_days(now())-to_days(hiredate))/365) as avgserveryear
from
emp e
group by
e.deptno;
27. -- 列出所有员工的姓名、部门名称和工资
select
d.dname,
e.ename,
e.sal
from
emp e
right join
dept d
on
e.deptno=d.deptno;
28. -- 列出所有部门的详细信息和人数
select
d.deptno,d.dname,d.loc,count(e.ename) as totalEmp
from
emp e
right join
dept d
on
e.deptno=d.deptno
group by
d.deptno,d.dname,d.loc;
29. -- 列出各种工作的最低工资及从事此工作的雇员姓名
t
select
e.job,min(e.sal) as minsal
from
emp e
group by
e.job;
将以上查询结果当成临时表t(job,minsal)
select
e.ename
from
emp e
join
(select
e.job,min(e.sal) as minsal
from
emp e
group by
e.job)t
on
e.job=t.job
where
e.sal=t.minsal;
30. -- 列出各个部门MANAGER的最低薪金
select
e.deptno,min(e.sal) as minsal
from
emp e
where
e.job='MANAGER'
group by
e.deptno;
31. -- 列出所有员工的年工资,按年薪从低到高排序
select ename,(sal+ifnull(comm,0))*12 as yearsal from emp order by yearsal asc;
32. -- 求出员工领导的薪水超过3000的员工名称和领导名称
select
e.ename,
b.ename as leadername
from
emp e
join
emp b
on
e.mgr=b.empno
where
b.sal > 3000;
-- COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):
SELECT COUNT(column_name) FROM table_name
-- COUNT(*) 函数返回表中的记录数:
SELECT COUNT(*) FROM table_name
33. -- 求部门名称中带有"S"字符的部门员工的工资合计、部门人数
select
d.dname,
sum(e.sal) as sumsal,
count(e.ename) as totalEmp
from
join
emp e
dept d
on
e.deptno=d.deptno
where
d.dname like '%s%'
group by
d.dname;
34 -- 给任职日期超过30年的员工加薪10%
update
emp_bak1
set
sal=sal*1.1
where
(to_days(now())-to_days(hiredate))/365 > 30;
-- 关于外键约束
1) .如果一张表的某个字段具有外键,那么这个字段不能设置为该表的主键并且不能自增,
并且这个字段所依赖的另一张表的字段应该为另一张表的主键并且设为自增.
2) .对从表进行插入数据时必须先确保从表所依赖的主表里面有数据.
外键约束使用最多的两种情况无外乎:
1)父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;
2)父表更新时子表也更新,父表删除时子表匹配的项也删除。
前一种情况,在外键定义中,我们使用ON UPDATE CASCADE ON DELETE RESTRICT ;(推荐)
后一种情况,可以使用ON UPDATE CASCADE ON DELETE CASCADE ;
Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构。
解决方法是在Mysql中取消外键约束: SET FOREIGN_KEY_CHECKS=0;
然后将原来表的数据导出到sql语句,重新创建此表后,再把数据使用sql导入,
然后再设置外键约束: SET FOREIGN_KEY_CHECKS=1;
-- 复合主键
所谓的复合主键 就是指你表的主键含有一个以上的字段组成.
例:
create table test
(
name varchar(19),
id number,
value varchar(10),
primary key (name,id)
)
上面的name和id字段组合起来就是你test表的复合主键 ,它的出现是因为你的name字段可能会出现重名,
所以要加上ID字段这样就可以保证你记录的唯一性 ,一般情况下,主键的字段长度和字段数目要越少越好 。
“主键是唯一的索引” 是有歧义的。应该是 “当表中只有一个主键时,它是唯一的索引;
当表中有多个主键时,称为复合主键,复合主键联合保证唯一索引”。
-- mysql中分页:
limit
格式1:
select .... limit m,n;
从索引为 m 条开始向后查找 n 条数据
就是从第 m+1 条 到 第 m+n 条
格式2:
select .... limit n;
等价于: select .... limit 0,n;
每一页需要的数据有
当前页内容 limit 查询
当前页码 从前台传递过去
每页显示的条数 固定
总条数 count(*)
总页数 总条数/每页显示的条数 Math.ceil(totalCount*1.0/pageSize)
开放中一般会将这五个参数封装一个 javabean(PageBean)
private List list; // 当前页内容 查询
private int currPage; // 当前页码 传递
private int pageSize; // 每页显示的条数 固定
private int totalCount; // 总条数 查询
private int totalPage; // 总页数 计算
-- DAO 层:
1. private List list; // 当前页内容 查询
public List findProductByPage(int currPage, int pageSize) throws Exception {
QueryRunner queryRunner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from product limit ?,?";
return queryRunner.query(sql, new BeanListHandler<>(Product.class), (currPage - 1) * pageSize, pageSize);
}
使用BeanListHandler
-- BeanListHandler:
用于将结果集的每一行数据转换为Javabean,再将这个Javabean添加到ArrayList中.
-- BeanHandler:
用于获取结果集中的第一行数据,并将其封装到JavaBean对象
2. private int totalCount; // 总条数 查询 count(*)
public int getCount() throws Exception {
QueryRunner queryRunner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select count(*) from product";
return ((Long) queryRunner.query(sql, new ScalarHandler())).intValue();
}
使用: ScalarHandler 获取结果集中的第一列
-- 在页面展示
1. 添加首页 上一页的超链接
2. 判断是否是第一页.若是第一页不显示首页和上一页
[首页]
[上一页]
3. 判断是否是最后一页,若是最后一页,不展示尾页和下一页
[下一页]
[尾页]
4. 第几页/共几页
第${pb.currPage }页/共${pb.totalPage }页
5. 显示所有页码,页面多的时候,采用前五后四的方式,只需要控制 begin 和 end
begin 判断当前页-5>0?当前页-5:1
end 判断当前页+4>总页数?总页数:当前页+4
var="n">
判断是否是当前页,若不是当前页,添加超链接
${n }
判断是否是当前页,若是当前页,不添加超链接
${n }
-- 注意:
double(5,2): 该小数长度为5个,小数占2个
例如: 999.99
一张表只能有一个主键,但是这个主键可以包含多个字段
-- 开发中处理一对多:
为了保证数据的有效性和完整性,添加约束(外键约束),在多表的一方添加外键约束(不是必须的,也可以通过 java 程序来控制)
在开发中,我,我们将一对多的关系,一方称之为主表或者一表,多方称之为多表或者从表,
为了表示一对多的关系,一般会在多表的一方添加一个字段,字段名称自定义(建议:主表的名称_id) ★
字段类型一般和主表的主键的类型保持一致,我们称这个字段为外键.
-- 添加了外键约束之后有如下特点:
1. 主表中不能删除从表中已引用的数据
2. 从表中不能添加主表中不存在的数据
注意: 一般外键在开发中不直接使用,因为添加外键之后,对数据的测试(增删改查),很不方便,
所以一般在项目全部完成之后才会对表进行外键约束.
-- 在开发中处理多对多:
引入一张中间表,存放两张表的主键,一般会将这两个字段设置为联合主键,这样就可以将多对多的关系拆分成两个一对多了
为了保证数据的有效性和完整性,需要在中间表上添加两个外键约束(不是必须的,也可以通过 java 程序来控制)
-- 多表查询:
内连接:
格式1: 显示的内连接
select a.*,b.* from a [inner] join b on ab的连接条件(强烈推荐★)
格式2: 隐式的内连接
select a.*,b.* from a,b where ab的连接条件(不推荐)
例:
SELECT `user`.username,orders.* FROM `user`,orders where `user`.id=orders.user_id;
SELECT `user`.*,orders.* FROM `user` JOIN orders ON `user`.id=orders.user_id;
外连接:
左外连接:
select a.*,b.* from a left [outer] join b on 连接条件;
意思:
先展示 join 左边的 (a) 表的所有数据,根据条件关联查询 join 右边的表(b),符合条件则展示出来,不符合以 null 值展示.
例:
SELECT `user`.*,orders.* FROM `user` LEFT JOIN orders ON `user`.id=orders.user_id;
注意: 只需要掌握左外连接即可,右外连接和左外连接等价.
-- 子查询:
是将一个查询的结果作为一张临时表
数据库备份:
1). 通过图形化工具备份(navicat)
2). 通过命令备份(不需要登录数据库,cmd命令即可)
备份:
例:
mysqldump -uroot -pzhc store>d:\1.sql
还原:
前提需要先手动创建数据库
例:
mysql -uroot -pzhc haha
DECIMAL(N,M)中M值的是小数部分的位数,若插入的值未指定小数部分或者小数部分不足M位则会自动补到M位小数,
若插入的值小数部分超过了M为则会发生截断,截取前M位小数。N值得是整数部分加小数部分的总长度,
也即插入的数字整数部分不能超过N-M位,否则不能成功插入,会报超出范围的错误。