一、数据库
之前通过流去操作文件保存数据的弊端: 1. 执行效率低 2. 开发成本高 3. 一般只能保存小量数据 4. 只能保存文本数据
什么是DB
什么是DBMS
- DataBaseManagementSystem 数据库管理系统(软件) ,用于管理保存数据的文件集合,用于和程序员进行交互,常见的DBMS有:Oracle MySQL DB2 SQLServer Sqlite ,DBMS具备网络访问能力
SQL
- Structured Query Language:结构化查询语言,用户程序员和DBMS进行交互,用于程序员告诉DBMS到底对数据进行什么操作的
数据库的分类(了解)
- 关系型数据库:经过数学理论验证可以将现实生活中的各种关系保存到数据库,这种就称为关系型数据库。保存数据以表为单位
- 非关系数据库:一般都是为了解决某些特定场景的问题比如:缓存,高并发访问,Redis数据库(以key-value形式保存数据)
常见的关系型数据
- MySQL: 属于Oracle公司的产品,08被Sun公司收购,09年Sun公司被Oracle收购,开源免费,被收购后发布5.5版本使用Oracle的部分技术,性能提高了30%以上,用户量增多,计划把MySQL闭源 原MySQL程序员离开Oracle创建了MariaDB 老板女儿Maria。市场排名第一
- Oracle: 排名第二,闭源 性能最高 收费最贵
- DB2: IBM公司产品 闭源项目
- SQLServer:微软公司产品 闭源
- Sqlite:轻量级数据库,安装包几十k,应用在嵌入式设备或移动设备上,
开源和闭源
打开客户端连接MySQL
- 在终端中执行: mysql -uroot -p 回车 如果有密码写密码 回车 如果没有密码则直接回车
和数据库相关的SQL
查询所有数据库
创建数据库
查看数据库详情
- show create database db1;
创建数据库指定字符集
- create database db2 character set gbk/utf8;
删除数据库
练习: 创建db2 db3 db4 db5 里面3,4,5字符集为gbk 最后删除每一个
使用数据库
- use db1;
查询所有: show databases 创建 : create database db1; 查询单个 show create database db1; 指定字符集 create database db1 character set gbk/utf8; 删除 drop database db1; 使用 use db1;
和表相关的SQL
查询所有表
创建表
- create table 表名(字段1名 字段1的类型,字段2名 字段2的类型,.....); create table person(name varchar(10),age int); -创建一个学生表(student) 保存学号id,姓名name,年龄age,语文chinese,数学math,英语english create table student(id int,name varchar(10),age int,chinese int,math int,english int);
查看表详情
- show create table 表名; show create table person;
创建表时指定表的引擎和字符集
- create table t1(name varchar(10)) engine=myisam charset=gbk;
表的引擎
- innodb:支持数据库的高级操作如:外键、事务等,默认引擎
- myisam:只支持基础的增删改查操作
SQL格式:
- 可以有换行
- 最后以;结尾
- 关键字之间需要有空格(可以写多个空格,建议写一个)
数据库 查询所有 show databases; 创建 create database db1; 查询详情 show create database db1; 指定字符集 create database db1 character set gbk/utf8; 删除 drop database db1; 使用 use db1;
表相关 查询所有 show tables; 创建 create table t1(name varchar(10),age int); 查询详情 show create table t1; 指定引擎和字符集: create table t1(name varchar(10),age int) engine=myisam/innodb charset=gbk/utf8;
查看表字段
删除表
修改表相关
- 修改表名
- rename table 原名 to 新名; rename table student to stu;
- 修改表的引擎和字符集
- alter table 表名 engine=myisam/innodb charset=utf8/gbk; alter table stu engine=myisam charset=gbk;
- 添加表字段
- 最后面: alter table 表名 add 字段名 字段类型;
- 最前面: alter table 表名 add 字段名 字段类型 first;
- xxx的后面: alter table 表名 add 字段名 字段类型 after xxx; create table hero(name varchar(10)); alter table hero add age int; alter table hero add id int first; alter table hero add sal int after name;
- 删除表字段
- alter table 表名 drop 字段名; alter table hero drop sal;
- 修改表字段的名字和类型
- alter table 表名 change 原字段名 新字段名 新字段类型; alter table hero change name heroname varchar(5);
- 修改表字段的类型和位置
-
alter table 表名 modify 字段名 类型 位置; alter table hero modify age int first(after xxx);
-
创建表 create table t1(name varchar(10)) engine=myisam charset=gbk;
- 查询所有 show tables;
- 表详情 show create table t1;
- 表字段 desc t1;
- 删除表 drop table t1; -修改表相关 改表名: rename table t1 to t2; 改引擎字符集: alter table t1 engine=myisam/innodb charset=gbk/utf8; 添加字段: alter table t1 add age int first(after xxx); 删除字段: alter table t1 drop age; 修改字段名称和类型: alter table t1 change sal salary int; 修改字段类型和位置: alter table t1 modify age int first(after name);
练习:
- 创建数据库newdb并使用, 里面创建员工表temp只有name字段 引擎为myisam 字符集为gbk create database newdb; use newdb; create table temp(name varchar(10)) engine=myisam charset=gbk;
- 修改表名为emp rename table t_emp to emp;
- 修改引擎为innodb 字符集为utf8 alter table emp engine=innodb charset=utf8;
- 添加部门编号字段deptno 在最后面 alter table emp add deptno int;
- 添加员工编号 empno在最前面 alter table emp add empno int first;
- 添加salary字段在name的后面 alter table emp add salary int after name;
- 修改salary字段名字为sal,把sal放在empno的后面 alter table emp change salary sal int; alter table emp modify sal int after empno;
- 删除sal字段 alter table emp drop sal;
- 删除表 drop table emp;
- 删除数据库 drop database newdb;
数据相关
插入数据
create table emp(id int,name varchar(10),age int,sal int);
- 全表插入数据:
- insert into emp values(1,'Tom',18,3000);
- 指定字段插入数据:
- insert into emp (name,age) values('Jerry',19);
- insert into emp (name) values('李白');
- 批量插入数据: insert into emp values(3,'刘备',28,6000),(4,'张飞',20,5000),(5,'关羽',25,9000); insert into emp (name,age) values('悟空',500),('八戒',400),('沙僧',200);
查询数据
- 查询全部数据的全部字段信息 select * from emp;
- 查询所有员工的姓名和年龄 select name,age from emp;
- 查询年龄在25岁以下的员工信息 select * from emp where age<25;
- 查询工资3000块钱的员工姓名、年龄、工资 select name,age,sal from emp where sal=3000;
修改数据
- 修改Tom的工资为3333 update emp set sal=3333 where name='Tom';
- 修改30岁以下的工资为666 update emp set sal=666 where age<30;
- 修改id等于3的名字为吕布 年龄为55 工资为20000 update emp set name='吕布', age=55, sal=20000 where id=3;
- 修改工资为null的工资为800 update emp set sal=800 where sal is null;
删除数据
- 删除id=1的员工 delete from emp where id=1;
- 删除年龄在25岁以下的员工 delete from emp where age<25;
- 删除全部数据 delete from emp;
insert into t1 (字段名1,字段名2) values(值1,值2),(值1,值2); select name,age from t1 where id<5; update t1 set 字段名=值, 字段名=值 where id=5; delete from t1 where id<3;
练习:
- 创建hero表如果存在则先删除再创建, id 姓名name 类型type 金币money
- 插入以下数据 1 诸葛亮 法师 18888 , 2 孙悟空 打野 18888 ,3 小乔 法师 6888,4 黄忠 射手 8888, 5 刘备 战士 6888
- 修改所有18888的为28888
- 修改所有打野为刺客
- 删除价格为6888的英雄
- 修改孙悟空为猪八戒
- 删除id为1,2,3的英雄
- 修改所有英雄的类型为已阵亡
- 删除所有数据
- 删除表
中文字符问题
课程回顾:
数据库相关
- 查询所有 show databases;
- 创建 create database db1 character set utf8/gbk;
- 查看详情 show create database db1;
- 删除 drop database db1;
- 使用 use db1;
表相关
- 创建 create table t1(name varchar(10),age int) engine=myisam/innodb charset=gbk/utf8;
- 查询所有 show tables;
- 查看表详情 show create table t1;
- 查看表字段 desc t1;
- 删除表 drop table t1;
- 修改表
- 修改表名 rename table t1 to t2;
- 修改引擎 alter table t1 engine=myisam/innodb charset=gbk/utf8;
- 添加字段 alter table t1 add age int first(after xxx);
- 删除字段 alter table t1 drop age;
- 修改名称和类型 alter table t1 change age newAge int;
- 修改类型和位置 alter table t1 modify age int first(after xxx);
数据相关
- 插入数据 insert into 表名 (name,age) values(值1,值2),(值1,值2),(值1,值2);
- 查询数据 select name,age from 表名 where id<5;
- 修改数据 update 表名 set age=18 where id=5;
- 删除数据 delete from 表名 where id=3;
二、课程回顾
数据库相关SQL
- 查询所有数据库 show databases;
- 创建数据库 create database db1 character set utf8/gbk;
- 查看详情 show create database db1;
- 删除数据库 drop database db1;
- 使用数据库 use db1;
表相关SQL
- 查询所有表 show tables;
- 创建表 create table t1(name varchar(10),age int) engine=innodb/myisam charset=utf8/gbk;
- 查看详情 show create table t1;
- 表字段 desc t1;
- 删除表 drop table t1;
- 改表名 rename table t1 to t2;
- 改引擎字符集 alter table t1 engine=innodb/myisam charset=utf8/gbk;
- 添加字段 alter table t1 add age int first/ after xxx;
- 删除字段 alter table t1 drop age;
- 修改字段名字和类型 alter table t1 change sal salary int;
- 修改类型和位置 alter table t1 modify sal int first/after xxx;
数据相关
- 插入数据 insert into t1 (name,age) values(值1,值2),(值1,值2);
- 查询数据 select age,name from t1 where id<10;
- 修改数据 update t1 set age=18 where id=10;
- 删除数据 delete from t1 where id=10;
练习:
- 创建数据库db2指定字符集为utf8 并使用,在数据库中,创建emp表里面有id,name,age,salary,部门名称(dept) create database db2 character set utf8; use db2; create table emp(id int,name varchar(10),age int,salary int,dept varchar(10));
- 往上面表格中插入 刘关张三人 和 取经四人,工资在3000-8000随意设置,年龄随意,id为1-7,刘关张属于三国部,剩下4个人属于取经部 insert into emp values(1,'刘备',25,4000,'三国部'),(2,'关羽',24,8000,'三国部'),(3,'张飞',22,3000,'三国部'),(4,'悟空',250,5000,'取经部'),(5,'八戒',350,6000,'取经部'),(6,'沙僧',450,7000,'取经部'),(7,'唐僧',50,8000,'取经部');
- 给表格添加一个性别字段在年龄的后面 alter table emp add gender varchar(5) after age;
- 修改所有的性别字段值为男 update emp set gender='男';
- 添加一个貂蝉,性别女,年龄随意,工资7000,部门为三国部 insert into emp values(8,'貂蝉',18,'女',7000,'三国部');
- 修改年龄小于30岁的员工工资为200 update emp set salary=200 where age<30;
- 修改取经部的所有人性别为未知 update emp set gender='未知' where dept='取经部';
- 查询三国部的员工姓名和工资 select name,salary from emp where dept='三国部'
- 删除所有女员工 delete from emp where gender='女';
- 删除部门中工资低于5000的员工 delete from emp where salary<5000;
主键约束 primary key
- 主键:用于表示数据唯一性的字段称为主键
- 约束: 是给表字段添加的限制条件
- 主键约束:限制主键字段值不能重复并且非空 (唯一且非空) create table t1(id int primary key,name varchar(10)); insert into t1 values(1,'Tom'); insert into t1 values(1,'Jerry');//失败 重复 insert into t1 values(null,'ABC');//失败 不能为null
- 自增: autoincrement create table t2(id int primary key autoincrement,name varchar(10)); insert into t2 values(null,'AAA'); insert into t2 values(2,'AAA'); insert into t2 values(10,'mm'); insert into t2 values(null,'AAA');
- 当字段值为null的时候值会自己增长
- 自增字段值也可以手动赋值
- 增长规则:从曾经出现的最大值基础上+1
- 自增数值只增不减 (delete清空表 自增数值并不清零)
注释 comment
- 创建表声明字段的时候给字段添加的介绍 create table t3(id int primary key auto_increment comment '这是一个主键',name varchar(10) comment '这是员工的姓名');
`和'
:用于修饰表名和字段名 可以省略 create table
t4(
idint,
name` varchar(10));
- ':用于修饰字符串
数据冗余
- 如果表设计不够合理,保存大量数据的同时可能随之会出现大量重复数据,这些重复数据的现象就称为数据冗余,通过拆分表的形式解决冗余问题
练习:设计表保存以下数据:
- 集团总部下面的市场部下的市场A部的员工刘备,工资8000,性别男,年龄25
- 教学部下 Java教学部的员工苍老师,工资100000,性别男,年龄18
- 创建员工表 create table emp(id int primary key auto_increment,name varchar(10),sal int,gender varchar(5),age int,deptid int);
- 创建部门表 create table dept(id int primary key auto_increment,name varchar(10),parentid int);
- 插入数据: insert into dept values(null,'集团总部',null); insert into dept values(null,'市场部',1); insert into dept values(null,'市场部A',2); insert into emp values(null,'刘备',8000,'男',25,3); insert into dept values(null,'教学部',1); insert into dept values(null,'Java教学部',4); insert into emp values(null,'苍老师',100000,'男',18,5); -设计表保存以下数据:
- 保存男装分类(category)下西服分类下的商品皮尔卡丹西服,价格9800,库存98件
- 保存家用电器分类下,电视机分类下的小米电视,价格2500,库存108件
三、
课程回顾:
数据库相关SQL
- 查询所有 show databases;
- 创建 create database db1 character set utf8/gbk;
- 查看详情 show create database db1;
- 删除 drop database db1;
- 使用 use db1;
表相关SQL
- 查询所有 show tables;
- 创建表 create table t1(name varchar(10),age int);
- 查看详情 show create table t1;
- 字段信息 desc t1;
- 删除表 drop table t1;
- 删除并创建新的 truncate table t1;
- 修改表名 rename table t1 to t2;
- 改引擎和字符集 alter table t1 engine=myisam/innodb charset=utf8/gbk;
- 添加字段 alter table t1 add age int first/after xxx;
- 删除字段 alter table t1 drop age;
- 修改名称和类型 alter table t1 change age newAge int;
- 修改类型和位置 alter table t1 modify age int first/after xxx;
数据相关
- 插入数据 insert into t1 (name,age) values(值1,值2),(值1,值2);
- 查询数据 select name,age from t1 where age<30;
- 修改数据 update t1 set age=18, name='aaa' where id=3;
- 删除数据 delete from t1 where id=10;
day02
- 主键约束+自增 唯一且非空 primary key auto_increment
- 注释: comment
- '和`
- 冗余:重复数据 通过拆分表解决
- 事务:数据库中执行sql语句的最小工作单元,保证里面的多条SQL语句全部成功或全部失败 show variables like '%autocommit%'; set autocommit=0/1; 提交commit 回滚rollback 回滚点 savepoint s1; rollback to s1;
- SQL分类
- DDL 数据定义语言 包括:create alter drop truncate 不支持事务
- DML 数据操作语言 包括:insert delete update select(DQL) 支持事务
- DQL 数据查询语言 包括:select
- TCL 事务控制语言 包括:commit rollback savepoint 。。。
- DCL 数据控制欲要 分配用户权限相关SQL
- 数据类型
- 整数: int(m) 和bigint m代表显示长度 需要结合zerofill使用
- 浮点数:double(m,d) m代表总长度 d代表小数长度 decimal超高精度浮点数
- 字符串:char固定长度 执行效率高 最大255 varchar可变长度 节省空间 最大65535超高255建议使用text
- 日期: date保存年月日 time保存时分秒 datetime:9999-12-31 默认为null timestamp:最大2038-1-19 默认值为当前时间
is null 和 is not null
- 查询emp表中没有上级领导mgr的员工编号empno,姓名ename,工资sal select empno,ename,sal from emp where mgr is null;
- 查询emp表中没有奖金comm的员工姓名,工资,奖金 select ename,sal,comm from emp where comm is null;
- 查询有奖金的所有员工信息 select * from emp where comm is not null;
别名
- 将查询到的员工姓名ename改成‘姓名’ select ename from emp; select ename as '姓名' from emp; select ename '姓名' from emp; select ename 姓名,sal 工资 from emp;
去重 distinct
- 查询emp表中出现的所有职位job select distinct job from emp;
比较运算符 >,<,>=,<=,=,!=和<>
- 查询工资小于等于1600的所有员工的姓名和工资 select ename,sal from emp where sal<=1600;
- 查询部门编号是20的所有员工姓名、职位和部门编号deptno select ename,job,deptno from emp where deptno=20;
- 查询职位是manager的所有员工姓名和职位 select ename,job from emp where job='manager';
- 查询部门不是10号部门的所有员工姓名和部门编号(两种写法) select ename,deptno from emp where deptno!=10; select ename,deptno from emp where deptno<>10;
- 查询商品表titem中单价price等于23的商品信息 select title,price from titem where price=23;
- 查询商品表中单价不等于8443的商品信息 select * from t_item where price!=8443;
and 和 or
- and等效java中的&&
- or等效java中的||
- 查询工资大于2000并且是10号部门的员工信息 select * from emp where sal>2000 and deptno=10;
- 查询不是10号部门并且工资大于等于1600的员工姓名,工资,部门编号 select ename,sal,deptno from emp where deptno!=10 and sal>=1600;
- 查询部门是30号部门或者上级领导mgr为7698的员工姓名,职位,上级领导和部门编号 select ename,job,mgr,deptno from emp where deptno=30 or mgr=7698;
- 查询有上级领导并且工资低于2000并且是20号部门的员工信息 select * from emp where mgr is not null and sal<2000 and deptno=20;
in
- 查询emp表中工资是5000,1500,3000的员工信息 select * from emp where sal=5000 or sal=1500 or sal=3000; select * from emp where sal in(5000,1500,3000);
between x and y 包含x和y
- 查询工资在2000到3000之间的员工姓名和工资 select ename,sal from emp where sal>=2000 and sal<=3000; select ename,sal from emp where sal between 2000 and 3000;
模糊查询 like
- _:代表单个未知字符
- %:代表0或多个未知字符
- 举例:
- 以a开头的字符串 a%
- 以m结尾 %m
- 包含x %x%
- 第二个字符是a _a%
- 倒数第三个字母是m %m__
- 以a开头并且倒数第二个字母是b a%b_
- 案例:
- 查询名字中包含a的所有员工姓名和工资 select ename,sal from emp where ename like '%a%';
- 查询标题中包含记事本的商品标题及商品价格 select title,price from t_item where title like '%记事本%';
- 查询单价低于100的记事本(title包含记事本) select * from t_item where title like '%记事本%' and price<100;
- 查询单价在50到200之间的得力商品(title包含得力) select * from t_item where price between 50 and 200 and title like '%得力%';
- 查询商品分类为238和917的商品信息 select * from titem where categoryid in(238,917);
- 查询有赠品的商品信息 (卖点sellpoint中包含赠字) select * from titem where sell_point like '%赠%';
- 查询有图片image的得力商品信息 select * from t_item where image is not null and title like '%得力%';
- 查询和得力无关的商品信息(title不包含得力) select * from t_item where title not like '%得力%';
- 查询价格在50到100以外的商品信息 select * from t_item where price not between 50 and 100;
排序 order by
- order by 关键字, by后面写排序的字段名称 默认是升序,
- asc升序 desc降序
- 查询所有员工的姓名和工资按照工资升序排序 select ename,sal from emp order by sal;
- 查询10号部门的所有员工信息,按照工资降序排序 select * from emp where deptno=10 order by sal desc;
- 查询所有带燃字的商品,按照单价升序排序 select * from t_item where title like '%燃%' order by price;
- 查询所有dell商品按照分类categoryid升序排序 select * from titem where title like '%dell%' order by category_id;
- 查询所有员工按照部门升序排序如果部门一致则按照工资降序排序 select * from emp order by deptno,sal desc;
- 查询所有商品分类和单价按照分类降序排序,如果分类相同则按照单价升序排序 select categoryid,price from titem order by category_id desc,price;
分页查询 limit
- limit 跳过的条数,请求的数量(每页的数量)
- 查询员工表中工资降序的前5条数据 select * from emp order by sal desc limit 0,5;
- 查询员工表中工资降序的第3页的4条数据 select * from emp order by sal desc limit 8,4;
- 查询商品表中价格升序的前10条数据 select * from t_item order by price limit 0,10;
- 查询商品表中价格低于100元的商品信息第三页的三条数据 select * from t_item where price<100 limit 6,3;
- 查询10号和30号部门的员工工资在前三名的员工信息 select * from emp where deptno in(10,30) order by sal desc limit 0,3;
concat()函数
- 把concat内部的参数拼接到一起
- 查询员工姓名和工资,要求工资单位是元
select ename,concat(sal,'元') 工资 from emp;
数值计算 + - * / %(mod(7,2)等效 7%2)
- 查询商品表中每个商品的单价,库存及总价值(单价库存) select price,num,pricenum from t_item;
- 查询员工表中每个员工的姓名,工资,及年终奖(五个月的工资) select ename,sal,sal*5 年终奖 from emp;
日期相关函数
- 获取当前的年月日时分秒 select now();
- 获取当前的日期 current select curdate();
- 获取当前的时间 select curtime();
- 从年月日时分秒中提取年月日 select date(now());
- 从年月日时分秒提取时分秒 select time(now());
- 从年月日时分秒中提取时间分量 年 月 日 时 分 秒
- extract(year from now())
- extract(month from now())
- extract(day from now())
- extract(hour from now())
- extract(minute from now())
- extract(second from now()) select extract(year from now());
- 查询员工表中的所有员工姓名和入职的年份 select ename,extract(year from hiredate) from emp;
- 日期格式化 date_format(时间,格式)
- %Y:四位年 2018
- %y:两位年 18
- %m:两位月 05
- %c:一位月 5
- %d:日
- %H: 24小时
- %h: 12小时
- %i: 分
- %s: 秒 select date_format(now(),'%Y年%m月%d日 %H时%i分%s秒');
- 查询商品名称和商品的上传日期(格式:x年x月x日) select title,dateformat(createdtime,'%Y年%m月%d日') from t_item;
- 把非标准的日期字符串转成标准的时间格式 strtodate(时间字符串,格式) 14.08.2018 08:00:00 select strtodate('14.08.2018 08:00:00','%d.%m.%Y %H:%i:%s');
ifnull(x,y)函数
- age=ifnull(x,18) 如果x的值为null 则age=18 如果不为null则 age=x
- 修改员工表中奖金为null的值为0 update emp set comm=ifnull(comm,0);
聚合函数
- 用于对多条数据进行统计
- 求和 sum(字段名)
- 查询emp中10号部门的工资总和 select sum(sal) from emp where deptno=10;
- 平均值 avg(字段名)
- 查询emp表中所有员工的工资平均值 select avg(sal) from emp;
- 最大值 max(字段名)
- 查询30号部门的员工的最高奖金 select max(comm) from emp where deptno=30;
- 最小值 min(字段名)
- 查询商品表中价格最便宜的商品的单价 select min(price) from t_item;
- 统计数量 count(字段名) 一般使用count(*)
- 统计30号部门有多少人 select count(*) from emp where deptno=30;
聚合函数练习:sum(),max(),min(),avg(),count(*)
- 统计工资在2500以上的员工人数 select count(*) from emp where sal>2500;
- 查询工资在1000到3000以内的最大奖金 select max(comm) from emp where sal between 1000 and 3000;
- 查询30号部门的最大奖金,最高工资,工资平均值,工资总和,并对查询结果起别名 select max(comm) 最大奖金,max(sal) 最高工资, avg(sal) 平均工资,sum(sal) 工资总和 from emp where deptno=30;
- 查询价格在100元以内的商品数量 select count(*) from t_item where price<100;
- 查询名字包含a的员工数量 select count(*) from emp where ename like '%a%';
和字符串相关函数
- 获取字符串的长度 charlength(str); 获取所有员工的姓名和姓名的字符长度 select ename,charlength(ename) from emp;
- 获取字符串在另外一个字符串中出现的位置 instr(str,substr) select instr('abcdefg','d');
- 插入字符串 insert(str,start,length,newStr) select insert('abcdefg',3,2,'m'); //abmefg
- 转大写 转小写 select upper('abc'),lower('NBA');
- 左边截取和右边截取 select left('abcdefg',2) , right('abcdefg',2);
- 去两端空白 select trim(' a b ');
- 截取字符串 select substring('abcdefg',3,2);
- 重复 repeat(str,count) select repeat('ab',2);
- 替换 replace(str,old,new) select replace('This is mysql','my','your');
- 反转 reverse(str) select reverse('abc');
回顾:
- is null 和 is not null
- 别名
- 去重 distinct
- and 和 or
- 比较运算符 > < >= <= = !=和<>
- in
- between x and y
- like _单个未知 %0或多个未知
- order by age asc/desc,sal
- limit 12,3
- concat(abc,mm)
- 数值运算 + - * / %和 mod()
- 日期 now() curdate() curtime() date(now()) time(now()) extract(year/month/day/hour/minute/second from now()) dateformat(now(),'格式') Y y m c d H h i s , strto_date(时间字符串,格式)
- age=ifnull(x,y) 如果x=null age=y x!=null age=x
- 聚合函数 sum() avg() max() min() count(*)
- 字符串 char_length instr insert upper lower left right substring replace repeat reverse trim
作业:
1.案例:查询没有上级领导的员工的编号,姓名,工资
2.案例:查询emp表中没有奖金的员工的姓名,职位,工资,以及奖金
3.案例:查询emp表中含有奖金的员工的编号,姓名,职位,以及奖金
4.案例:查询含有上级领导的员工的姓名,工资以及上级领导的编号
5.案例:查询emp表中名字以‘S’开头的所有员工的姓名
6.案例:查询emp表中名字的最后一个字符是'S'的员工的姓名
7.案例:查询倒数的第2个字符是‘E’的员工的姓名
8.案例:查询emp表中员工的倒数第3个字符是‘N’的员工姓名
9.案例:查询emp表中员工的名字中包含‘A’的员工的姓名
10.案例:查询emp表中名字不是以'K'开头的员工的所有信息
11.案例:查询emp表中名字中不包含‘A’的所有员工的信息
12.案例:做文员的员工人数(job_id 中 含有 CLERK 的)
13.案例:销售人员 job: SALESMAN 的最高薪水
14.案例:最早和最晚入职时间
15.案例:查询类别 163的商品总库存量
16.案例:查询 类别 163 的商品
17.案例:查询商品价格不大于100的商品名称列表
18.案例:查询品牌是联想,且价格在40000以上的商品名称和价格
19.案例:查询品牌是三木,或价格在50以下的商品名称和价格
20.案例:查询品牌是三木、广博、齐心的商品名称和价格
21.案例:查询品牌不是联想、戴尔的商品名称和价格
22.案例:查找品牌是联想且价格大于10000的电脑名称
23.案例:查询联想或戴尔的电脑名称列表
24.案例:查询联想、戴尔、三木的商品名称列表
25.案例:查询不是戴尔的电脑名称列表
26.案例:查询所有是记事本的商品品牌、名称和价格
27.案例:查询品牌是末尾字符是'力'的商品的品牌、名称和价格
28.案例:名称中有联想字样的商品名称
29.案例:查询卖点含有'赠'产品名称
30.案例:查询emp表中员工的编号,姓名,职位,工资,并且工资在1000~2000之间。
31.案例:查询emp表中员工在10号部门,并且含有上级领导的员工的姓名,职位,上级领导编号以及所属部门的编号
32.案例:查询emp表中名字中包含'E',并且职位不是MANAGER的员工的编号,姓名,职位,以及工资。
33.案例:查询emp表中10号部门或者20号部门中员工的编号,姓名,所属部门的编号
34.案例:查询emp表中没有奖金或者名字的倒数第2个字母不是T的员工的编号,姓名,职位以及奖金
35.案例:查询工资高于3000或者部门编号是30的员工的姓名,职位,工资,入职时间以及所属部门的编号
36.案例:查询不是30号部门的员工的所有信息
37.案例:查询奖金不为空的员工的所有信息
38.案例:查询emp表中所有员工的编号,姓名,职位,根据员工的编号进行降序排列
39.案例:查询emp表中部门编号是10号或者30号中,所有员工姓名,职务,工资,根据工资进行升序排列
40.案例:查询emp表中所有的数据,然后根据部门的编号进行升序排列,如果部门编号一致,根据员工的编号进行降序排列
41.案例:查询emp表中工资高于1000或者没有上级领导的员工的编号,姓名,工资,所属部门的编号,以及上级领导的编号,根据部门编号进行降序排列,如果部门编号一致根据工资进行升序排列。
42.案例:查询emp表中名字中不包含S的员工的编号,姓名,工资,奖金,根据工资进行升序排列,如果工资一致,根据编号进行降序排列
43.案例:统计emp表中员工的总数量
44.案例:统计emp表中获得奖金的员工的数量
45.案例:求出emp表中所有的工资累加之和
46.案例:求出emp表中所有的奖金累加之和
47.案例:求出emp表中员工的平均工资
48.案例:求出emp表中员工的平均奖金
49.案例:求出emp表中员工的最高工资
50.案例:求出emp表中员工编号的最大值
51.案例:查询emp表中员工的最低工资。
52.案例:查询emp表中员工的人数,工资的总和,平均工资,奖金的最大值,奖金的最小值,并且对返回的列起别名。
53.案例:查询emp表中每个部门的编号,人数,工资总和,最后根据人数进行升序排列,如果人数一致,根据工资总和降序排列。
54.案例:查询工资在1000~3000之间的员工信息,每个部门的编号,平均工资,最低工资,最高工资,根据平均工资进行升序排列。
55.案例:查询含有上级领导的员工,每个职业的人数,工资的总和,平均工资,最低工资,最后根据人数进行降序排列,如果人数一致,根据平均工资进行升序排列
56.案例:查询工资在1000~3000之间每一个员工的编号,姓名,职位,工资
57.案例:查询emp表中奖金在500~2000之间所有员工的编号,姓名,工资以及奖金
58.案例:查询员工的编号是7369,7521,
59.案例:查询emp表中,职位是ANALYST,
60.案例:查询emp表中职位不是ANALYST,
课程回顾
- is null 和 is not null
- 别名
- 去重 distinct
- 比较运算符 > < >= <= = !=和<>
- and or
- in not in
- between x and y 包括xy
- like _代表单个未知 %代表0或多个未知
- 排序 order by 字段 asc/desc,字段
- 分页查询 limit 跳过条数,每页数量
- concat('aa','bb') aabb
- 日期相关: now() curdate() curtime() date(now()) time(now()) extract(year/month/day/hour/minute/second from now()), dateformat(时间,格式) %YymcdHhis strto_date(时间字符串,格式)
- 数值计算 + - * / % mod()
- ifnull age=ifnull(x,y)
- 聚合 sum() avg() max() min() count(*)
- 字符串 char_length() instr() insert() upper() lower() left() right() substring() trim() replace() repeat() reverse()
作业:
1.案例:查询没有上级领导的员工的编号,姓名,工资
select empno,ename,sal from emp where mgr is null;
2.案例:查询emp表中没有奖金的员工的姓名,职位,工资,以及奖金
select ename,job,sal,comm from emp where comm is null or comm=0;
3.案例:查询emp表中含有奖金的员工的编号,姓名,职位,以及奖金
select empno,ename,job,comm from emp where comm is not null and comm>0;
4.案例:查询含有上级领导的员工的姓名,工资以及上级领导的编号
select ename,sal,mgr from emp where mgr is not null;
5.案例:查询emp表中名字以‘S’开头的所有员工的姓名
select ename from emp where ename like 's%';
6.案例:查询emp表中名字的最后一个字符是'S'的员工的姓名
select ename from emp where ename like '%s';
7.案例:查询倒数的第2个字符是‘E’的员工的姓名
select ename from emp where ename like '%e_';
8.案例:查询emp表中员工的倒数第3个字符是‘N’的员工姓名
select ename from emp where ename like '%n__';
9.案例:查询emp表中员工的名字中包含‘A’的员工的姓名
select ename from emp where ename like '%a%';
10.案例:查询emp表中名字不是以'K'开头的员工的所有信息
select * from emp where ename not like 'k%';
11.案例:查询emp表中名字中不包含‘A’的所有员工的信息
select * from emp where ename not like '%a%';
12.案例:做文员的员工人数(job 中 含有 CLERK 的)
select count(*) from emp where job='clerk';
13.案例:销售人员 job: SALESMAN 的最高薪水
select max(sal) from emp where job='SALESMAN';
14.案例:最早和最晚入职时间
select min(hiredate),max(hiredate) from emp;
15.案例:查询类别 163的商品总库存量
select sum(num) from t_item where category_id=163;
16.案例:查询 类别 163 的商品
select * from t_item where category_id=163;
17.案例:查询商品价格不大于100的商品名称列表
select * from t_item where price<=100;
18.案例:查询品牌是联想,且价格在40000以上的商品名称和价格
select title,price from t_item where price>40000 and title like '%联想%';
19.案例:查询品牌是三木,或价格在50以下的商品名称和价格
select title,price from t_item where price<50 or title like '%三木%';
20.案例:查询品牌是三木、广博、齐心的商品名称和价格
select title,price from t_item where title like '%三木%' or title like '%广博%' or title like '%齐心%';
21.案例:查询品牌不是联想、戴尔的商品名称和价格
select title,price from t_item where title not like '%联想%' and title not like '%戴尔%';
22.案例:查找品牌是联想且价格大于10000的电脑名称
select title from t_item where price>10000 and title like '%联想%';
23.案例:查询联想或戴尔的电脑名称列表
select title from t_item where title like '%联想%' or title like '%戴尔%';
27.案例:查询品牌是末尾字符是'力'的商品的品牌、名称和价格
select title,price from t_item where title like '%力';
30.案例:查询emp表中员工的编号,姓名,职位,工资,并且工资在1000~2000之间。
select empno,ename,job,sal from emp where sal between 1000 and 2000;
31.案例:查询emp表中员工在10号部门,并且含有上级领导的员工的姓名,职位,上级领导编号以及所属部门的编号
select ename,job,mgr,deptno from emp
where deptno=10 and mgr is not null;
32.案例:查询emp表中名字中包含'E',并且职位不是MANAGER的员工的编号,姓名,职位,以及工资。
select empno,ename,job,sal from emp where ename like '%e%' and job!='manager';
33.案例:查询emp表中10号部门或者20号部门中员工的编号,姓名,所属部门的编号
select empno,ename,deptno from emp where deptno in(10,20);
34.案例:查询emp表中没有奖金或者名字的倒数第2个字母不是T的员工的编号,姓名,职位以及奖金
select empno,ename,job,comm from emp where comm>0 or ename not like '%t_';
35.案例:查询工资高于3000或者部门编号是30的员工的姓名,职位,工资,入职时间以及所属部门的编号
select ename,job,sal,hiredate,deptno from emp
where sal>3000 or deptno=30;
36.案例:查询不是30号部门的员工的所有信息
select * from emp where deptno!=30;
37.案例:查询奖金不为空的员工的所有信息
select * from emp where comm is not null;
38.案例:查询emp表中所有员工的编号,姓名,职位,根据员工的编号进行降序排列
select empno,ename,job from emp order by empno desc;
39.案例:查询emp表中部门编号是10号或者30号中,所有员工姓名,职务,工资,根据工资进行升序排列
select ename,job,sal from emp where deptno in(10,30) order by sal;
40.案例:查询emp表中所有的数据,然后根据部门的编号进行升序排列,如果部门编号一致,根据员工的编号进行降序排列
select * from emp order by deptno,empno desc;
41.案例:查询emp表中工资高于1000或者没有上级领导的员工的编号,姓名,工资,所属部门的编号,以及上级领导的编号,根据部门编号进行降序排列,如果部门编号一致根据工资进行升序排列。
select empno,ename,sal,deptno,mgr from emp where sal>1000 or mgr is null order by deptno desc,sal ;
42.案例:查询emp表中名字中不包含S的员工的编号,姓名,工资,奖金,根据工资进行升序排列,如果工资一致,根据编号进行降序排列
select empno,ename,sal,comm from emp where ename not like '%s%' order by sal,empno desc;
43.案例:统计emp表中员工的总数量
select count(*) from emp;
44.案例:统计emp表中获得奖金的员工的数量
select count(*) from emp where comm>0;
45.案例:求出emp表中所有的工资累加之和
select sum(sal) from emp;
46.案例:求出emp表中所有的奖金累加之和
select sum(comm) from emp;
47.案例:求出emp表中员工的平均工资
select avg(sal) from emp;
48.案例:求出emp表中员工的平均奖金
select avg(comm) from emp;
49.案例:求出emp表中员工的最高工资
select max(sal) from emp;
50.案例:求出emp表中员工编号的最大值
select max(empno) from emp;
51.案例:查询emp表中员工的最低工资。
select min(sal) from emp;
52.案例:查询emp表中员工的人数,工资的总和,平均工资,奖金的最大值,奖金的最小值,并且对返回的列起别名。
select count(*) 人数,sum(sal) 工资总和,avg(sal) 平均工资, max(comm) 奖金最大值,min(comm) 奖金最小值 from emp;
数学相关函数
- 向下取整 floor(num) select floor(3.84); //3
- 四舍五入 round(num); select round(3.84); // 4 -round(num,m) m代表小数位数 select round(3.84567,3); //3.846
- 非四舍五入 truncate(num,m) select truncate(3.84567,3);
- 随机数 rand() 0-1 5-10 0-5 select floor(rand()6) + 5; 3-8 0-5 select floor(rand()6) +3;
分组查询
- 分组查询通常和聚合函数结合使用,以组为单位进行统计
- 一般情况下,题目中每个xxx 就在group by后面写xxx
- 查询每个部门的最高工资 select deptno,max(sal) from emp group by deptno;
- 查询每个部门的平均工资 select deptno,avg(sal) from emp group by deptno;
- 查询每个分类下商品的最低价格 select categoryid,min(price) from titem group by category_id;
- 查询每个部门中工资大于1500的人数 select deptno,count(*) from emp where sal>1500 group by deptno;
- 查询每个领导的手下人数 select mgr,count(*) from emp where mgr is not null group by mgr;
- 查询每个商品分类的库存总量 select categoryid,sum(num) from titem group by category_id;
- 案例:查询emp表中每个部门的编号,人数,工资总和,最后根据人数进行升序排列,如果人数一致,根据工资总和降序排列。 select deptno,count(),sum(sal) from emp group by deptno order by count(),sum(sal) desc; select deptno,count(*) c,sum(sal) s from emp group by deptno order by c,s desc;
- 案例:查询工资在1000~3000之间的员工信息,每个部门的编号,平均工资,最低工资,最高工资,根据平均工资进行升序排列。 select deptno,avg(sal) a,min(sal),max(sal) from emp where sal between 1000 and 3000 group by deptno order by a;
- 案例:查询含有上级领导的员工,每个职业的人数,工资的总和,平均工资,最低工资,最后根据人数进行降序排列,如果人数一致,根据平均工资进行升序排列 select job,count(*) c,sum(sal),avg(sal) a,min(sal) from emp where mgr is not null group by job order by c desc,a;
-
如果需要使用多个字段进行分组 直接在group by 后面写多个字段名通过逗号分隔
-
查询每个部门下每个领导的手下人数 select deptno,mgr,count(*) from emp where mgr is not null group by deptno,mgr;
having
- where后面只能写普通字段的条件不能写聚合函数
- having后面可以写普通字段条件也可以写聚合函数,但是推荐在having后面只写聚合函数
-
having写在group by 的后面
-
select * from 表名 where ..... group by xxx having .... order by ..... limit ...;
-
查询每个部门的平均工资,要求平均工资大于2000 select deptno,avg(sal) a from emp group by deptno having a>2000;
- 查询每个分类的平均单价,过滤掉平均单价低于100的。 select categoryid,avg(price) a from titem group by category_id having a>=100;
练习:
- 查询每个分类商品的库存总量,要求总量高于19999 select categoryid,sum(num) s from titem group by category_id having s>19999;
- 查询分类id为238和917的两个分类的平均单价各是多少 select categoryid,avg(price) from titem where categoryid in (238,917) group by categoryid;
- 查询emp表中每个部门的平均工资高于2000的部门编号,部门人数,平均工资 最后根据平均工资降序排序 select deptno,count(*),avg(sal) a from emp group by deptno having a>2000 order by a desc;
- 查询emp表中工资在1000-3000之间的员工,每个部门的编号,工资总和,平均工资,要求过滤掉平均工资低于2000的部门,按照工资总和降序排序 select deptno,sum(sal) s,avg(sal) a from emp where sal between 1000 and 3000 group by deptno having a>=2000 order by s desc;
- 查询emp表中不是以s开头每个职位的名字,人数,工资总和,最高工资,过滤掉平均工资是3000的职位,根据人数升序排序,如果一致根据工资总和降序排序 select job,count(*) c,sum(sal) s,max(sal) from emp where job not like 's%' group by job having avg(sal)!=3000 order by c,s desc;
- 查询emp表每年入职的人数 select extract(year from hiredate) y,count(*) from emp group by y;
子查询
- 查询emp表工资最高的员工信息 select max(sal) from emp; select * from emp where sal=5000;
- 子查询 select * from emp where sal=(select max(sal) from emp);
- 查询emp表中工资高于平均工资的员工信息 select * from emp where sal>(select avg(sal) from emp);
-
查询和Jones相同工作的员工信息
select * from emp where job=(select job from emp where ename='jones') and ename!='jones';
- 查询工资最低的员工的所在部门同事信息 -求最低工资 select min(sal) from emp -通过最低工资得到这个员工的部门编号 select deptno from emp where sal=(select min(sal) from emp); -通过部门编号找到其它的员工信息 select * from emp where deptno=(select deptno from emp where sal=(select min(sal) from emp)) and sal!=(select min(sal) from emp);
- 查询最后入职的员工信息 select max(hiredate) from emp; select * from emp where hiredate=(select max(hiredate) from emp);
-
having 要写在 group by 后面
-
查询king的部门编号和部门名称 -得到部门编号 select deptno from emp where ename='king' -通过编号得到部门名称 select deptno,dname from dept where deptno=(select deptno from emp where ename='king');
- 查询有员工的部门信息(需要两张表) -得到员工表出现的部门编号 select distinct deptno from emp; -通过部门编号得到部门信息 select * from dept where deptno in (select distinct deptno from emp);
- 查询平均工资最高的部门信息(史诗级难度!!) -得到每个部门的平均工资 select deptno,avg(sal) from emp group by deptno; -得到最高的平均工资 select avg(sal) a from emp group by deptno order by a desc limit 0,1; -通过最高的平均工资得到对应的部门编号 select deptno from emp group by deptno having avg(sal)=(select avg(sal) a from emp group by deptno order by a desc limit 0,1); -通过部门编号得到部门信息 select * from dept where deptno in(select deptno from emp group by deptno having avg(sal)=(select avg(sal) a from emp group by deptno order by a desc limit 0,1));
- 子查询可以写在什么位置
- 写在where或having后面 当做查询条件的值
- 写在创建表的时候 把查询结果保存成一张新的表 create table emp_20 as (select * from emp where deptno=20);
-
写在from后面 当成一个虚拟表 必须有别名 select * from emp where deptno=20;
select ename,sal from (select * from emp where deptno=20) newtable;
关联查询
- 同时查询多张表的数据称为关联查询
- 查询每一个员工的姓名和对应的部门名称 select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;
- 查询在new york工作的员工信息 select * from emp e,dept d where e.deptno=d.deptno and d.loc='new york';
- 查询商品标题和所对应的分类名称 select i.title,c.name from titem i,titemcategory c where i.categoryid=c.id;
笛卡尔积
- 如果关联查询不写关联关系则结果为两张表的乘积,这个乘积称为笛卡尔积。
- 笛卡尔积为一种错误的查询结果,切记工作中不要出现
等值连接和内连接
-
等值连接和内连接查询到的内容一样,都为两张表中有关联关系的数据(交集部分)
-
等值连接: select * from A,B where A.x=B.x and A.age=18;
-
内连接: select * from A [inner] join B on A.x=B.x where A.age=18;
- 查询每一个员工的姓名和对应的部门名称 select e.ename,d.dname from emp e join dept d on e.deptno=d.deptno;
外连接
- 内连接和等值连接查询到的是交集部分的数据,外连接查询到的是某一张表的全部数据+另外一张表的交集数据
-
左/右外连接: select * from A left/right join B on A.x=B.x where A.age=18;
insert into emp (empno,ename) values(10010,'Tom');
- 查询所有员工姓名和对应的部门名称 select e.ename,d.dname from emp e left join dept d on e.deptno=d.deptno;
关联查询总结
- 关联查询的查询方式: 等值连接 内连接和外连接
- 如果想查询的数据为两张表的交集数据使用等值连接或内连接(推荐)
- 如果查询的数据是一张表的全部数据和另外一张表的交集数据则使用外连接
作业:
-
每个部门的人数,根据人数排序
-
每个部门中,每个主管的手下人数
-
每种工作的平均工资
-
每年的入职人数
-
少于等于3个人的部门信息
-
拿最低工资的员工信息
-
只有一个下属的主管信息
-
平均工资最高的部门编号
-
下属人数最多的人,查询其个人信息
-
拿最低工资的人的信息
-
最后入职的员工信息
-
工资多于平均工资的员工信息
-
查询员工信息,部门名称
-
员工信息,部门名称,所在城市
-
DALLAS 市所有的员工信息
-
按城市分组,计算每个城市的员工数量
-
查询员工信息和他的主管姓名
-
员工信息,员工主管名字,部门名
-
员工和他所在部门名
-
案例:查询emp表中所有员工的姓名以及该员工上级领导的编号,姓名,职位,工资
-
案例:查询emp表中名字中没有字母'K'的所有员工的编号,姓名,职位以及所在部门的编号,名称,地址
-
案例:查询dept表中所有的部门的所有的信息,以及与之关联的emp表中员工的编号,姓名,职位,工资
四、
课程回顾
- is null 和 is not null
- 别名
- 去重 distinct
- 比较运算符 > < >= <= = !=和<>
- and or
- in not in
- between x and y 包括xy
- like _代表单个未知 %代表0或多个未知
- 排序 order by 字段 asc/desc,字段
- 分页查询 limit 跳过条数,每页数量
- concat('aa','bb') aabb
- 日期相关: now() curdate() curtime() date(now()) time(now()) extract(year/month/day/hour/minute/second from now()), dateformat(时间,格式) %YymcdHhis strto_date(时间字符串,格式)
- 数值计算 + - * / % mod()
- ifnull age=ifnull(x,y)
- 聚合 sum() avg() max() min() count(*)
- 字符串 char_length() instr() insert() upper() lower() left() right() substring() trim() replace() repeat() reverse()
作业:
1.案例:查询没有上级领导的员工的编号,姓名,工资
select empno,ename,sal from emp where mgr is null;
2.案例:查询emp表中没有奖金的员工的姓名,职位,工资,以及奖金
select ename,job,sal,comm from emp where comm is null or comm=0;
3.案例:查询emp表中含有奖金的员工的编号,姓名,职位,以及奖金
select empno,ename,job,comm from emp where comm is not null and comm>0;
4.案例:查询含有上级领导的员工的姓名,工资以及上级领导的编号
select ename,sal,mgr from emp where mgr is not null;
5.案例:查询emp表中名字以‘S’开头的所有员工的姓名
select ename from emp where ename like 's%';
6.案例:查询emp表中名字的最后一个字符是'S'的员工的姓名
select ename from emp where ename like '%s';
7.案例:查询倒数的第2个字符是‘E’的员工的姓名
select ename from emp where ename like '%e_';
8.案例:查询emp表中员工的倒数第3个字符是‘N’的员工姓名
select ename from emp where ename like '%n__';
9.案例:查询emp表中员工的名字中包含‘A’的员工的姓名
select ename from emp where ename like '%a%';
10.案例:查询emp表中名字不是以'K'开头的员工的所有信息
select * from emp where ename not like 'k%';
11.案例:查询emp表中名字中不包含‘A’的所有员工的信息
select * from emp where ename not like '%a%';
12.案例:做文员的员工人数(job 中 含有 CLERK 的)
select count(*) from emp where job='clerk';
13.案例:销售人员 job: SALESMAN 的最高薪水
select max(sal) from emp where job='SALESMAN';
14.案例:最早和最晚入职时间
select min(hiredate),max(hiredate) from emp;
15.案例:查询类别 163的商品总库存量
select sum(num) from t_item where category_id=163;
16.案例:查询 类别 163 的商品
select * from t_item where category_id=163;
17.案例:查询商品价格不大于100的商品名称列表
select * from t_item where price<=100;
18.案例:查询品牌是联想,且价格在40000以上的商品名称和价格
select title,price from t_item where price>40000 and title like '%联想%';
19.案例:查询品牌是三木,或价格在50以下的商品名称和价格
select title,price from t_item where price<50 or title like '%三木%';
20.案例:查询品牌是三木、广博、齐心的商品名称和价格
select title,price from t_item where title like '%三木%' or title like '%广博%' or title like '%齐心%';
21.案例:查询品牌不是联想、戴尔的商品名称和价格
select title,price from t_item where title not like '%联想%' and title not like '%戴尔%';
22.案例:查找品牌是联想且价格大于10000的电脑名称
select title from t_item where price>10000 and title like '%联想%';
23.案例:查询联想或戴尔的电脑名称列表
select title from t_item where title like '%联想%' or title like '%戴尔%';
27.案例:查询品牌是末尾字符是'力'的商品的品牌、名称和价格
select title,price from t_item where title like '%力';
30.案例:查询emp表中员工的编号,姓名,职位,工资,并且工资在1000~2000之间。
select empno,ename,job,sal from emp where sal between 1000 and 2000;
31.案例:查询emp表中员工在10号部门,并且含有上级领导的员工的姓名,职位,上级领导编号以及所属部门的编号
select ename,job,mgr,deptno from emp
where deptno=10 and mgr is not null;
32.案例:查询emp表中名字中包含'E',并且职位不是MANAGER的员工的编号,姓名,职位,以及工资。
select empno,ename,job,sal from emp where ename like '%e%' and job!='manager';
33.案例:查询emp表中10号部门或者20号部门中员工的编号,姓名,所属部门的编号
select empno,ename,deptno from emp where deptno in(10,20);
34.案例:查询emp表中没有奖金或者名字的倒数第2个字母不是T的员工的编号,姓名,职位以及奖金
select empno,ename,job,comm from emp where comm>0 or ename not like '%t_';
35.案例:查询工资高于3000或者部门编号是30的员工的姓名,职位,工资,入职时间以及所属部门的编号
select ename,job,sal,hiredate,deptno from emp
where sal>3000 or deptno=30;
36.案例:查询不是30号部门的员工的所有信息
select * from emp where deptno!=30;
37.案例:查询奖金不为空的员工的所有信息
select * from emp where comm is not null;
38.案例:查询emp表中所有员工的编号,姓名,职位,根据员工的编号进行降序排列
select empno,ename,job from emp order by empno desc;
39.案例:查询emp表中部门编号是10号或者30号中,所有员工姓名,职务,工资,根据工资进行升序排列
select ename,job,sal from emp where deptno in(10,30) order by sal;
40.案例:查询emp表中所有的数据,然后根据部门的编号进行升序排列,如果部门编号一致,根据员工的编号进行降序排列
select * from emp order by deptno,empno desc;
41.案例:查询emp表中工资高于1000或者没有上级领导的员工的编号,姓名,工资,所属部门的编号,以及上级领导的编号,根据部门编号进行降序排列,如果部门编号一致根据工资进行升序排列。
select empno,ename,sal,deptno,mgr from emp where sal>1000 or mgr is null order by deptno desc,sal ;
42.案例:查询emp表中名字中不包含S的员工的编号,姓名,工资,奖金,根据工资进行升序排列,如果工资一致,根据编号进行降序排列
select empno,ename,sal,comm from emp where ename not like '%s%' order by sal,empno desc;
43.案例:统计emp表中员工的总数量
select count(*) from emp;
44.案例:统计emp表中获得奖金的员工的数量
select count(*) from emp where comm>0;
45.案例:求出emp表中所有的工资累加之和
select sum(sal) from emp;
46.案例:求出emp表中所有的奖金累加之和
select sum(comm) from emp;
47.案例:求出emp表中员工的平均工资
select avg(sal) from emp;
48.案例:求出emp表中员工的平均奖金
select avg(comm) from emp;
49.案例:求出emp表中员工的最高工资
select max(sal) from emp;
50.案例:求出emp表中员工编号的最大值
select max(empno) from emp;
51.案例:查询emp表中员工的最低工资。
select min(sal) from emp;
52.案例:查询emp表中员工的人数,工资的总和,平均工资,奖金的最大值,奖金的最小值,并且对返回的列起别名。
select count(*) 人数,sum(sal) 工资总和,avg(sal) 平均工资, max(comm) 奖金最大值,min(comm) 奖金最小值 from emp;
数学相关函数
- 向下取整 floor(num) select floor(3.84); //3
- 四舍五入 round(num); select round(3.84); // 4 -round(num,m) m代表小数位数 select round(3.84567,3); //3.846
- 非四舍五入 truncate(num,m) select truncate(3.84567,3);
- 随机数 rand() 0-1 5-10 0-5 select floor(rand()6) + 5; 3-8 0-5 select floor(rand()6) +3;
分组查询
- 分组查询通常和聚合函数结合使用,以组为单位进行统计
- 一般情况下,题目中每个xxx 就在group by后面写xxx
- 查询每个部门的最高工资 select deptno,max(sal) from emp group by deptno;
- 查询每个部门的平均工资 select deptno,avg(sal) from emp group by deptno;
- 查询每个分类下商品的最低价格 select categoryid,min(price) from titem group by category_id;
- 查询每个部门中工资大于1500的人数 select deptno,count(*) from emp where sal>1500 group by deptno;
- 查询每个领导的手下人数 select mgr,count(*) from emp where mgr is not null group by mgr;
- 查询每个商品分类的库存总量 select categoryid,sum(num) from titem group by category_id;
- 案例:查询emp表中每个部门的编号,人数,工资总和,最后根据人数进行升序排列,如果人数一致,根据工资总和降序排列。 select deptno,count(),sum(sal) from emp group by deptno order by count(),sum(sal) desc; select deptno,count(*) c,sum(sal) s from emp group by deptno order by c,s desc;
- 案例:查询工资在1000~3000之间的员工信息,每个部门的编号,平均工资,最低工资,最高工资,根据平均工资进行升序排列。 select deptno,avg(sal) a,min(sal),max(sal) from emp where sal between 1000 and 3000 group by deptno order by a;
- 案例:查询含有上级领导的员工,每个职业的人数,工资的总和,平均工资,最低工资,最后根据人数进行降序排列,如果人数一致,根据平均工资进行升序排列 select job,count(*) c,sum(sal),avg(sal) a,min(sal) from emp where mgr is not null group by job order by c desc,a;
-
如果需要使用多个字段进行分组 直接在group by 后面写多个字段名通过逗号分隔
-
查询每个部门下每个领导的手下人数 select deptno,mgr,count(*) from emp where mgr is not null group by deptno,mgr;
having
- where后面只能写普通字段的条件不能写聚合函数
- having后面可以写普通字段条件也可以写聚合函数,但是推荐在having后面只写聚合函数
-
having写在group by 的后面
-
select * from 表名 where ..... group by xxx having .... order by ..... limit ...;
-
查询每个部门的平均工资,要求平均工资大于2000 select deptno,avg(sal) a from emp group by deptno having a>2000;
- 查询每个分类的平均单价,过滤掉平均单价低于100的。 select categoryid,avg(price) a from titem group by category_id having a>=100;
练习:
- 查询每个分类商品的库存总量,要求总量高于19999
- 查询分类id为238和917的两个分类的平均单价各是多少
- 查询emp表中每个部门的平均工资高于2000的部门编号,部门人数,平均工资 最后根据平均工资降序排序
- 查询emp表中工资在1000-3000之间的员工,每个部门的编号,工资总和,平均工资,要求过滤掉平均工资低于2000的部门,按照工资总和降序排序
五、
课程回顾:
- 分组查询 group by 字段,字段
- having 和group by结合使用,用于添加聚合函数的条件
- 子查询(嵌套查询) 可以嵌套n层,1. 写在where和having后面 2.from后面当虚拟表 3. 写在创建表的时候
- 关联查询:
- 等值连接:select * from A,B where A.x=B.x and A.age=18;
- 内连接:select * from A join B on A.x=B.x where A.age=18;
- 外连接:select * from A left/right join B on A.x=B.x where A.age=18;
作业:
- 每个部门的人数,根据人数排序 select deptno,count(*) c from emp group by deptno order by c;
-
每个部门中,每个主管的手下人数 select deptno,mgr,count(*) from emp where mgr is not null group by deptno,mgr;
select d.deptno,e.mgr,count(e.ename) from emp e right join dept d on e.deptno=d.deptno where e.mgr is not null group by d.deptno,e.mgr;
- 查询每个部门的人数(结果中包含40号部门) select d.deptno,count(e.ename) from emp e right join dept d on e.deptno=d.deptno group by d.deptno;
- 每种工作的平均工资 select job,avg(sal) from emp group by job;
- 每年的入职人数 select extract(year from hiredate) y,count(*) from emp group by y;
- 少于等于3个人的部门信息 select d.*,count(e.ename) c from emp e right join dept d on e.deptno=d.deptno group by d.deptno having c<=3;
- 拿最低工资的员工信息 select * from emp where sal=(select min(sal) from emp);
- 只有一个下属的主管信息 -查询只有一个下属的主管编号 select mgr from emp where mgr is not null group by mgr having count()=1; -通过得到的主管编号查询主管的详情 select * from emp where empno in (select mgr from emp where mgr is not null group by mgr having count()=1);
- 平均工资最高的部门编号 -得到最高的平均工资 select avg(sal) a from emp group by deptno order by a desc limit 0,1; -通过平均工资值去查询对应的部门编号 select deptno from emp group by deptno having avg(sal)=(select avg(sal) a from emp group by deptno order by a desc limit 0,1);
- 下属人数最多的人,查询其个人信息 -得到最多的下属人数 select count() c from emp group by mgr order by c desc limit 0,1; -通过人数查询对应的领导编号 select mgr from emp group by mgr having count()=(select count(*) c from emp group by mgr order by c desc limit 0,1); -通过领导编号得到个人信息 select * from emp where empno in(select mgr from emp group by mgr having count()=(select count() c from emp group by mgr order by c desc limit 0,1));
- 拿最低工资的人的信息 select * from emp where sal=(select min(sal) from emp);
- 最后入职的员工信息 select * from emp where hiredate=(select max(hiredate) from emp);
- 工资多于平均工资的员工信息 select * from emp where sal>(select avg(sal) from emp);
- 查询员工信息,部门名称 select e.*,d.dname from emp e join dept d on e.deptno=d.deptno;
- 员工信息,部门名称,所在城市 select e.*,d.dname,d.loc from emp e join dept d on e.deptno=d.deptno;
- DALLAS 市所有的员工信息 select e.* from emp e join dept d on e.deptno=d.deptno where d.loc='DALLAS';
-
按城市分组,计算每个城市的员工数量 select d.loc,count(e.ename) from emp e right join dept d on e.deptno=d.deptno group by d.loc;
-
查询员工信息和他的主管姓名 select e.*,m.ename from emp e join emp m on e.mgr=m.empno;
create table tdept(id int,name varchar(10),parentid int); insert into t_dept values(1,'集团总部',null), (2,'市场部',1), (3,'教学部',1), (4,'java教学部',3);
- 查询每个部门的名称和上级部门的名称 select d.name,m.name from tdept d join tdept m on d.parent_id=m.id;
-
员工信息,员工主管名字,部门名 select e.ename,m.ename,d.dname from emp e join emp m on e.mgr=m.empno join dept d on e.deptno=d.deptno;
-
员工和他所在部门名 select e.ename,d.dname from emp e join dept d on e.deptno=d.deptno;
-
案例:查询emp表中所有员工的姓名以及该员工上级领导的编号,姓名,职位,工资 select e.ename,m.empno,m.ename,m.job,m.sal from emp e left join emp m on e.mgr=m.empno;
-
案例:查询emp表中名字中没有字母'K'的所有员工的编号,姓名,职位以及所在部门的编号,名称,地址 select e.empno,e.ename,e.job,d.* from emp e left join dept d on e.deptno=d.deptno where e.ename not like '%k%';
- 案例:查询dept表中所有的部门的所有的信息,以及与之关联的emp表中员工的编号,姓名,职位,工资 select d.*,e.empno,e.ename,e.job,e.sal from emp e right join dept d on e.deptno=d.deptno;
表设计之关联关系
一对一
- 什么是一对一关系: 有AB两张表,其中A表的一条数据对应B表的一条数据,同时B表的一条数据也对应A表中的一条数据
- 应用场景: 用户表和用户信息扩展表、商品表和商品信息扩展表
- 外键: 表中用于建立关系的字段称为外键,一张表有可能有多个外键,但只会有一个主键
- 如何建立关系:在从表中添加外键指向主表的主键
- 练习: 创建表保存以下数据 表名 user 和 userinfo 用户名wukong 密码abcd 昵称悟空 性别男 地址花果山
wzt admin 武则天 女 大陆 Superman 123456 超人 男 铁岭 create table user(id int primary key auto_increment,username varchar(10),password varchar(10)); create table userinfo(userid int,nick varchar(10),gender varchar(5), loc varchar(20)); insert into user values(null,'wukong','abcd'),(null,'wzt','admin'),(null,'superman','123456'); insert into userinfo values(1,'悟空','男','花果山'),(2,'武则天','女','大陆'),(3,'超人','男','铁岭');
- 查询每个用户名对应的昵称 select u.username,ui.nick from user u join userinfo ui on u.id=ui.userid;
- 查询超人的用户名 select u.username from user u join userinfo ui on u.id=ui.userid where ui.nick='超人';
- 查询性别是男的用户名和密码 select u.username,u.password from user u join userinfo ui on u.id=ui.userid where ui.gender='男';
- 查询是否存在 用户名:wukong 密码:abc的用户 (查询符合条件的数据条数) select count(*) from user where username='wukong' and password='abc';
一对多
- 什么是一对多:有AB两张表,A表中的一条数据对应B表中的多条数据,同时B表中的一条数据对应A表中的一条
- 应用场景: 用户表和部门表,商品表和分类表
- 如何建立关系:在多的一端添加外键指向另外一张表的主键
- 练习: 创建emp表和dept表 create table emp(id int primary key autoincrement,name varchar(10),deptid int); create table dept(id int primary key autoincrement,name varchar(10)); insert into dept values(null,'神仙'),(null,'妖怪'); insert into emp values(null,'猪八戒',1),(null,'白骨精',2),(null,'蜘蛛精',2);
- 查询每个员工的姓名和对应的部门名称 select e.name,d.name from emp e join dept d on e.deptid=d.id;
- 查询妖怪部的员工姓名 select e.name from emp e join dept d on e.deptid=d.id where d.name='妖怪';
多对多
- 什么是多对多:有AB两张表,A表中的一条数据对应B表中的多条数据,同时B表中的一条数据对应A表中的多条
- 应用场景: 老师表和学生表
- 如何建立关系:通过第三张关系表保存两张主表的关系
- 练习: 创建老师表,学生表和关系表 create table teacher(id int primary key autoincrement,name varchar(10)); create table student(id int primary key autoincrement,name varchar(10)); create table t_s(tid int,sid int);
- 往以上表中保存苍老师的学生小刘和小丽,传奇老师的学生小刘,小王和小丽 insert into teacher values(null,'苍老师'),(null,'传奇老师'); insert into student values(null,'小刘'),(null,'小王'),(null,'小丽'); insert into t_s values(1,1),(1,3),(2,1),(2,2),(2,3);
- 查询每个学生姓名和对应的老师姓名 select s.name,t.name from student s join t_s ts on s.id=ts.sid join teacher t on t.id=ts.tid;
- 查询苍老师的学生都有谁 select s.name from student s join t_s ts on s.id=ts.sid join teacher t on t.id=ts.tid where t.name='苍老师';
- 查询小丽的老师是谁 select t.name from student s join t_s ts on s.id=ts.sid join teacher t on t.id=ts.tid where s.name='小丽';
自关联
- 在当前表中添加外键外键的值指向当前表的主键,这种关联方式称为自关联 create table person(id int primary key auto_increment,name varchar(10),mgr int); 保存以下数据: 如来->唐僧->悟空->猴崽子 insert into person values(null,'如来',null),(null,'唐僧',1),(null,'悟空',2),(null,'猴崽子',3);
- 查询每个人的名字和上级的名字 select p.name,m.name 上级 from person p left join person m on p.mgr=m.id;
表设计案例:权限管理
- 实现权限管理功能需要准备三张主表和两张关系表
-
创建表: create table user (id int,name varchar(10)); create table role (id int,name varchar(10)); create table module (id int,name varchar(10));
create table ur (uid int, rid int); create table rm (rid int, mid int);
- 插入数据: insert into user values(1,'刘德华'),(2,'凤姐'); insert into role values(1,'男游客'),(2,'男会员'),(3,'女游客'),(4,'女管理员'); insert into module values(1,'男浏览'),(2,'男发帖'),(3,'女浏览'),(4,'女发帖'),(5,'女删帖'); -保存角色和权限的关系: insert into rm values(1,1),(2,1),(2,2),(3,3),(4,3),(4,4),(4,5); -保存用户和角色的关系 刘德华男会员和女游客 凤姐:女管理员和男游客 insert into ur values(1,2),(1,3),(2,1),(2,4);
- 查询每个用户的权限有哪些 select u.name,m.name from user u join ur ur on u.id=ur.uid join rm rm on rm.rid=ur.rid join module m on m.id=rm.mid;
- 查询凤姐的权限 select u.name,m.name from user u join ur ur on u.id=ur.uid join rm rm on rm.rid=ur.rid join module m on m.id=rm.mid where u.name='凤姐';
- 查询拥有男浏览权限的用户有谁 select u.name,m.name from user u join ur ur on u.id=ur.uid join rm rm on rm.rid=ur.rid join module m on m.id=rm.mid where m.name='男浏览';
六、
课程回顾:
day01
- 数据库相关SQL
- 查询所有 show databases;
- 创建 create database db1 character set utf8/gbk;
- 查看详情 show create database db1;
- 删除 drop database db1;
- 使用 use db1;
- 表相关SQL
- 创建表 create table t1(id int,name varchar(10)) engine=myisam/innodb charset=utf8/gbk;
- 查看所有 show tables;
- 查看详情 show create table t1;
- 删除 drop table t1;
- 查看字段 desc t1;
- 修改表名 rename table t1 to t2;
- 修改引擎字符集 alter table t1 engine=myisam/innodb charset=utf8/gbk;
- 添加字段 alter table t1 add age int;
- 删除字段 alter table t1 drop age;
- 修改字段名称和类型 alter table t1 change age xxx 类型;
- 修改字段类型和位置 alter table t1 modify age 类型 first/after xxx;
- 数据相关:
- 插入数据 insert into t1 (字段名1,字段名2) values(值1,值2),(值1,值2),(值1,值2);
- 查询数据 select name,age from emp where id<10;
- 修改数据 update t1 set age=18 where id=10;
- 删除数据 delete from t1 where id<5;
day02
- 主键约束: 唯一且非空 primary key
- 自增: auto_increment 只增不减 从历史最大值基础+1
- 注释 comment
- '和`
- 数据冗余: 重复数据 拆分表解决
- 事务:数据库中执行SQL语句的最小工作单元 可以保证事务中的多条SQL语句全部成功或全部失败
- SQL分类:
- DDL: 数据定义语言 包括 create alter drop truncate 不支持事务
- DML:数据操作语言 包括 insert update delete select(DQL) 支持事务
- DQL:数据查询语言 包括 select
- TCL:事务控制语言 包括:commit rollback savepoint rollback to。。
- DCL:数据控制语言 用于分配用户权限
- 数据类型
- 整数: int(m) bigint m代表显示长度 需要结合zerofill使用
- 浮点数: double(m,d) m代表总长度 d小数长度 decimal(m,d)
- 字符串: char 固定长度 最大255 执行效率高 varchar可变长度 最大65535 超过255建议使用text text可变长度 最大65535
- 日期: date年月日 time时分秒 datetime 默认值null 最大 9999-12-31 timestamp 默认当前时间 最大 2038-1-19
day03
- is null 和 is not null
- 别名
- 去重 distinct
- 比较运算符 > < >= <= = !=和<>
- and和or
- in
- between x and y 包含x和y
- like _单个未知 %代表0或多个未知
- 排序 order by 字段名 desc,字段名
- limit 跳过的条数,每页条数
- concat(s1,s2) s1s2
- 聚合:求和sum() 平均值avg() 最大值max() 最小值min() 统计数量count(*)
- 日期相关: now() curdate() curtime() date(now()) time(now()) extract(year/month/day/hour/minute/second from now()) dateformat(时间,'格式') 格式: %YymcdHhis strto_date('非标准时间','格式')
- ifnull(x,y)
- 字符串相关:char_length() instr() insert() trim() left() right() substring() upper() lower() replace() repeat() reverse()
day04
- 数学相关: floor() round() truncate() rand()
- 分组查询: group by 字段名,字段名
- having后面写聚合函数的条件 where后面写普通字段的条件
- 子查询(嵌套查询) 可以嵌套n层 可以写在 where和having后面做查询条件的值 写在from后面当成虚拟的表 写在创建表的时候 create table 表名 as (子查询);
- 关联查询:同时查询多个表的数据,
- 关联查询的查询方式: 等值连接和内连接、外连接
- 当查询的数据为两张表的交集部分数据时用等值或内连接(推荐)
- select * from A,B where A.x=B.x and A.age=18;
- select * from A join B on A.x=B.x where A.age=18;
- 当查询的数据为某一张表的全部数据和另外一张表的交集数据时使用外连接
- - select * from A left/right join B on A.x=B.x where A.age=18;
- 笛卡尔积:关联查询不写关联关系 会得到两张表的乘积 称为笛卡尔积
day05
- 一对一: 在从表中添加外键指向主表的主键
- 一对多: 在多的一端 添加外键 指向另外一张表的主键
- 多对多: 通过第三张关系表建立关系
- 自关联: 自己的外键指向自己表的主键称为自关联,当需要保存上级关系时使用自关联
- 权限管理案例:用户表 角色表 权限表 用户角色关系表 角色权限关系表
面试题:
- 设计表 交易时间、交易金额、交易类型、姓名、性别、关系
-
流水表: create table trade(id int primary key autoincrement,time date,money int,type varchar(5),personid int);
-
人物表: create table person(id int primary key auto_increment,name varchar(10),gender varchar(5),rel varchar(5)); 如果考虑数据冗余 可以把交易类型 和关系 单独拆分到一张表当中
- 插入数据 insert into person values(null,'刘德华','男','亲戚'),(null,'杨幂','女','亲戚'),(null,'马云','男','同事'),(null,'特朗普','男','朋友'),(null,'貂蝉','女','朋友'); insert into trade values(null,'2018-08-20',-20,'微信',1), (null,'2018-04-20',500,'现金',2), (null,'2018-05-10',-50,'现金',2), (null,'2018-05-20',50000,'支付宝',3), (null,'2018-06-20',-5,'支付宝',3), (null,'2018-06-21',2000,'微信',4), (null,'2018-08-20',-20000,'微信',5);
- 统计2018年2月15号到现在的所有红包收益 select sum(money) from trade where time>strtodate('2018年2月15号','%Y年%c月%d号');
- 查询2018年2月15号到现在金额大于100,所有女性亲戚的名字和红包金额 select p.name,t.money from trade t join person p on t.personid=p.id where time>strto_date('2018年2月15号','%Y年%c月%d号') and t.money not between -100 and 100 and p.gender='女' and p.rel='亲戚';
- 查询三个平台分别收入的红包金额 select type,sum(money) from trade where money>0 group by type;
视图
- 数据库中包含多种对象,表和视图都是数据库中的对象,视图可以理解成一张虚拟的表,视图本质就是取代了一段sql查询语句
-
为什么使用视图:因为有些数据的查询需要写大量的SQL语句,每次书写比较麻烦,通过使用视图相当于把当了的SQL查询语句进行保存,下次从视图中查询就不用再次书写大量SQL语句,从而提高开发效率。隐藏敏感字段
-
视图格式: create view 视图名 as (子查询); create view vemp10 as (select * from emp where deptno=10); delete from emp where sal=1300; select * from vemp10;
-
创建一个没有工资的视图 create view vempnosal as (select empno,ename,comm,mgr from emp);
- 创建视图,视图中显示每个部门的工资总和,平均工资,最高工资,最低工资 create view vempinfo as (select deptno,sum(sal),avg(sal),max(sal),min(sal) from emp group by deptno);
- 视图的分类:
- 简单视图:创建视图的时候不包含:去重、分组、函数、关联查询的视图称为简单视图,可以对视图中的数据进行增删改查
- 复杂视图:和简单视图相反,只能进行查询操作
- 简单视图的增删改操作 操作方式和操作table一样
- 插入数据 insert into vemp10 (empno,ename,deptno) values (10011,'悟空',10); insert into vemp10 (empno,ename,deptno) values (10012,'八戒',20);(数据污染)
- 往视图中插入一条在视图中不显示但是在原表中显示的数据,称为数据污染
- 通过 with check option 关键字解决数据污染问题 create view vemp20 as (select * from emp where deptno=20) with check option; -测试: insert into vemp20 (empno,ename,deptno) values (10013,'刘备',20); //成功 insert into vemp20 (empno,ename,deptno) values (10014,'张飞',30); //失败
- 删除和修改:只能操作视图中存在的数据
- 别名:如果创建视图时使用别名 则 操作视图时只能使用别名 create view vemp30 as (select ename name from emp where deptno=30); select * from vemp30 where ename='james';
视图总结:
- 视图时数据库中的对象,可以理解成一张虚拟的表,本质就是一段SQL语句
- 作用: 重用SQL,隐藏敏感字段
- 分类:简单视图(不包含去重 分组 函数 关联查询,可以增删改查)和复杂视图(反之,查询)
- 通过with check option 解决数据污染
- 删除和修改时 只能操作视图中存在的数据
- 起了别名 只能用别名、
约束
非空约束 not null
-
字段值不能为null
create table t1(id int,age int not null); insert into t1 values(1,18);//成功 insert into t1 values(2,null);//失败
唯一约束 unique
- 字段的值不能重复 create table t2(id int,age int unique); insert into t2 values(1,20);//成功 insert into t2 values(2,20);//失败
主键约束
- 字段的值唯一且非空
- 创建表时添加主键约束: create table t3(id int primary key,age int);
- 创建表之后添加主键约束: create table t3(id int,name varchar(10)); alter table t3 add primary key(id);
- 删除主键约束 alter table t3 drop primary key;
自增
- 数值只增不减
- 从历史最大值的基础上+1
- 字段值赋值为null的时候自动+1
- 使用delete 删除全表数据 自增数值不变
- 使用truncate 自增清零
默认约束 default
- 给字段添加默认值,当插入数据不给该字段赋值时 默认值生效 create table t4(id int,age int default 10); insert into t4 values(1,20); insert into t4 values(2,null); insert into t4 (id) values(3);//默认值生效
检查约束 check
- 语法支持,但是没有效果. create table t5(id int,age int check(age>10)); insert into t5 values(1,5);
外键约束
- 外键约束作用:为了保证两个表之间的关系正确建立
- 插入数据时外键值可以为null,可以重复,但是不能是另外一张表不存在的数据
- 被依赖的表不能被先删除
- 被依赖的数据不能先删除
- 如何使用外键:
- 创建部门表 create table dept(id int primary key auto_increment,name varchar(10));
- 创建员工表 create table emp(id int primary key autoincrement,name varchar(10),deptid int, constraint fkdept foreign key(deptid)references dept(id));
- 介绍: constraint 约束名称 foreign key(外键字段名)references 表名(字段名)
- 测试: insert into dept values(null,'神仙'),(null,'妖怪'); insert into emp values(null,'悟空',1);//成功 insert into emp values(null,'八戒',1);//成功 insert into emp values(null,'超人',3);//失败 drop table dept;//失败 delete from dept where id=2;//成功 delete from dept where id=1;//失败
索引
- 什么是索引: 索引是数据库中提高查询效率的技术,类似于字典的目录
- 为什么使用索引:如果不使用索引数据会零散的保存在每一个磁盘块当中,查询数据时需要挨个的遍历每一个磁盘块查找数据,如果数据量超级大,遍历每一个磁盘块是件非常耗时的事情,添加索引后,会将磁盘块以树桩结构进行保存,查询数据时会有目的性的访问部分磁盘块,因为访问的磁盘块数量降低所以能起到提高查询效率的作用
- 索引是越多越好吗? 不是,因为索引会占磁盘空间,通过某个字段创建的索引可能永远用不上,则这个索引完全没有存在的意义,只需要对查询时频繁使用的字段创建索引
- 有索引就一定好吗? 不一定,如果数据量小使用索引反而会降低查询效率
- 索引的分类(了解)
- 聚集索引(聚簇索引): 通过主键创建的索引为聚集索引,添加了主键约束的表会自动添加聚集索引,聚集索引的树桩结构中保存了数据
- 非聚集索引:通过非主键字段创建的索引叫做非聚集索引,树桩结构中只保存了数据所在磁盘块的地址并没有数据。
- 导入数据:
-
windows电脑 把文件放到D盘下 source d:/item_backup.sql;
-
Linux系统 把文件放到桌面 source /home/soft01/桌面/item_backup.sql;
- 测试:
- show tables; 看是否有item2这张表
- select count(*) from item2; 看是否有172万条数据
- select * from item2 where title='100'; //看一下耗时 1.1秒
-
创建索引的格式: create index 索引名 on 表名(字段名[(字符长度)]);
create index iitemtitle on item2(title);
-创建完后继续执行 select * from item2 where title='100'; //看一下耗时 0.02秒
-
查看索引: show index from item2;
-
删除索引 drop index 索引名 on 表名; drop index iitemtitle on item2;
-
复合索引 通过多个字段创建的索引称为复合索引 -格式:create index 索引名 on 表名(字段1,字段2); 频繁使用多个字段进行数据查询时为了提高查询效率可以创建复合索引 select * from item2 where title='100' and price<100; create index iitem2title_price on item2(title,price);
- 总结:
- 索引是用于提高查询效率的技术,类似目录
- 索引会占用磁盘空间不是越多越好
- 如果数据量小的话 添加索引会降低查询效率
- 尽量不要在频繁改动的表上添加索引
事务
- 数据库中执行SQL语句的最小工作单元,保证事务中的多条SQL全部成功或全部失败
- 事务的ACID特性:
- Atomicity: 原子性, 最小不可拆分 保证全部成功或全部失败
- Consistency: 一致性,从一个一致状态到另外一个一致状态
- Isolation:隔离性,多个事务之间互相隔离互不影响
- Durability:持久性, 事务提交后 数据持久保存到数据库文件中
- 事务相关指令:
- 查看自动提交状态: show variables like '%autocommit%'
- 修改自动提交: set autocommit=0/1;
- 提交: commit;
- 回滚: rollback;
- 保存回滚点: savepoint s1;
- 回滚到指定回滚点: rollback to s1;
group_concat() 分组连接函数
- 查询员工表中 每个部门的所有员工工资 要求所有工资显示到一条数据中 select deptno,group_concat(sal) from emp group by deptno;
- 查询员工表中每个部门 的员工姓名和对应的工资 要求显示到一条数据中 select deptno,group_concat(ename,':',sal) from emp group by deptno;
面试题:
有个学生表student (id,name,subject,score) create table student(id int primary key autoincrement,name varchar(10),subject varchar(5),score int); 保存以下数据: 张三 语文 66 , 张三 数学 77 , 张三 英语 55 , 张三 体育 77 李四 语文 59 , 李四 数学 88 , 李四 英语 78 , 李四 体育 95 王五 语文 75 , 王五 数学 54 , 王五 英语 98 , 王五 体育 88 insert into student values(null,'张三','语文',66), (null,'张三','数学',77),(null,'张三','英语',55),(null,'张三','体育',77); insert into student values(null,'李四','语文',59), (null,'李四','数学',88),(null,'李四','英语',78),(null,'李四','体育',95); insert into student values(null,'王五','语文',75), (null,'王五','数学',54),(null,'王五','英语',98),(null,'王五','体育',88); 1. 查询每个人的平均分 从大到小排序 select name,avg(score) a from student group by name order by a desc; 2. 每个人的姓名 科目 成绩 一行显示出来 select name,groupconcat(subject,':',score) from student group by name; 3. 查询每个人的最高分和最低分 select name,max(score),min(score) from student group by name; 4. 查询每个人不及格的科目以及分数和不及格的科目数量 select name,group_concat(subject,':',score),count(*) from student where score<60 group by name;
七、
JDBC
- JDBC:Java DataBase Connectivity,java数据库连接,实际上jdbc是java中的一套和数据库进行交互的api(application program interface 应用程序编程接口)
- 为什么使用JDBC:因为Java程序员需要连接多种数据库,为了避免每一种数据库都学习一套新的api,Sun公司提出了一个JDBC的接口,各个数据库的厂商根据此接口写实现类(驱动),这样java程序员只需要掌握JDBC接口的调用,即可访问任何数据库。
如何使用JDBC连接MySQL数据库
- 创建Maven工程
- 登录maven私服的网站 maven.tedu.cn 外网 maven.aliyun.com 首页搜索MySQL 找到 5.1.6版本 把坐标复制到pom.xml中
- 创建Demo01.java类 添加main方法 -通过以下代码连接数据库并执行sql语句 //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 获取连接对象 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/db3", "root", "root"); //3. 创建SQL执行对象 Statement stat = conn.createStatement(); //4. 执行SQL String sql = "drop table if exists jdbc"; stat.execute(sql); System.out.println("执行完成"); //5. 关闭资源 stat.close(); conn.close();
JUnit Test 单元测试
- 在无参无返回值的方法上面添加@Test注解,通过右键 run as 执行 绿色代表执行成功,红色执行失败
执行SQL的方法
- execute(); 此方法可以执行任意的SQL 但是推荐执行DDL(数据定义语言 create drop alter truncate) 返回值为boolean值 返回值代表的是是否有结果集(只有查询语句有结果集)
- executeUpdate(); 增删改操作全部使用此方法 返回值为int 表示生效的行数
-
executeQuery(); 此方法执行查询操作 返回ResultSet 通过while循环遍历 代码如下:
//执行查询 得到的结果封装在了resultset中
ResultSet rs = stat.executeQuery(sql);
//遍历结果集
while(rs.next()) {
int empno = rs.getInt("empno");
String name = rs.getString("ename");
double sal = rs.getDouble("sal");
System.out.println(empno+name+sal);
}
- 从ResultSet中获取数据的两种方式:
- 通过表字段的名称获取
- 通过结果中字段的位置获取 (以本次查询的字段顺序为准,并非表字段的顺序)
自定义模板代码
window->preferense->java->editor->templates->new
八、
数据库连接池 DBCP
PreparedStatement预加载的SQL执行对象
- 好处:
- 代码更直观,简洁
- 可以避免SQL注入, 因为在预编译时已经把sql逻辑固定锁死,不会被之后替换进去的值改变原有逻辑
批量操作batch
因为每次sql的执行都需要和数据库服务器进行数据传输,如果执行的sql太多每次和数据库进行交互浪费资源执行效率低,使用批量操作可以把多条SQL语句合并到一次交互中,这样可以提高执行效率
- Statement //添加到批量操作 stat.addBatch(sql1); stat.addBatch(sql2); stat.addBatch(sql3); //执行批量操作 stat.executeBatch();
-
PreparedStatement
stat = conn.prepareStatement(sql);
stat.setString(1, "刘备");
stat.setString(2, "aaa");
//添加到批量处理
stat.addBatch();
stat.setString(1, "关羽");
stat.setString(2, "bbb");
//添加到批量处理
stat.addBatch();
stat.setString(1, "张飞");
stat.setString(2, "ccc");
//添加到批量处理
stat.addBatch();
//执行
stat.executeBatch();
事务
- 关闭自动提交 conn.setAutoCommit(false/true);
- 提交 conn.commit();
- 回滚 conn.rollback();
- 案例 参见代码:Demo11.java
获取自增主键的值
create table team(id int primary key auto_increment,name varchar(10));
create table player(id int primary key auto_increment,name varchar(10),teamid int);
//请输入球队名称 火箭
//请输入球员名称 姚明
//请输入球队名称 火箭
//请输入球员名称 麦迪
数据库的元数据和表的元数据 代码参见:Demo14.java