一 入门篇
数据库(Database)是按照数据结构来组织的、存储和管理数据的仓库
数据库现在已经成为数据管理的重要技术,也是计算机的重要分子。
分类 | 产品 | 特点 |
小型 | Access、foxbase | 负载量小,用户大概100人以内;成本在千元之内,对安全性要求不高 |
中型 | Sqlservler、mysql | 负载量,日访问在500-10000;成本在万元以内;满足日常安全需求 |
大型 | Sybase、db2、oracle | 海量负载,可以处理海量数据;安全性高,相对贵
|
1.DBMS
(1)什么是DBMS
1).数据库管理系统是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库, 简称DBMS。大部分DBMS提供数据定义语言DDL和数据操作语言DML
2).简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。
3).当前主流的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft
Access、MySQL 等。
(2)Oracle Database
Oracle Database,又名 Oracle RDBMS,或简称 Oracle。是甲骨文公司的一款关系数据库管理系统。系统可移植性好、使用方便、功能强,适用于各类大、中、小、 微机环境。它是一种高效率、可靠性好的 适应高吞吐量的数据库解决方案。
2.SQL语言介绍
什么是SQL
SQL为数据库的语言 它包含三部分
分类 命令
数据定义语言 DDL create:创建;drop:删除;alter:修改;rename:重命名; truncate:截断
数据操作语言 DML insert:插入;delete:删除;update:更新;select:查
数据控制语言 DCL grant:授权;revoke:回收权利;commit:提交事务;rollback:回滚事务
3.表Table
1.理解
- 表是从属用户的,查询表(用户名.表名),当前用户查询自己的表是,用户名可以省略,其他用户查询 别的用户表 ,不能省略,同时必须存在权限。
2)表是逻辑表(概念表),不是物理表
- 表结构
DB | java |
表名 | 类名 |
字段名 | 属性名 |
字段类型: number(长度[,精度]) :number(5) number(5,2) char(定长长度) : char(5) a+4 个空 varchar2(变成长度):varchar2(5) a aaa date timestamp | 属性类型: 基本类型l 引用类型 |
字段约束:约制行为 -->创建表结构加入, 操作数据才生效 主键约束:唯一+非空 外键约束 非空约束 唯一约束: 可以为空 默认约束 检查约束
| 方法检查条件
|
记录:数据
| 对象:new
|
4.Scott用户表
(1).查看表
SQL> select TABLE_NAME from tabs;
dept:部门表
emp:雇员表
salgrade:工资等级表
bonus:奖金表
(2).查看表结构
SQL> desc emp
Name Type Nullable Default Comments
-------- ------------ -------- ------- --------
EMPNO NUMBER(4)
ENAME VARCHAR2(10) Y
JOB VARCHAR2(9) Y
MGR NUMBER(4) Y
HIREDATE DATE Y
SAL NUMBER(7,2) Y
COMM NUMBER(7,2) Y
DEPTNO NUMBER(2) Y
5.三范式
1.1NF:是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值属性不能有多个值或者不能有重复的属性。
2.2NF:是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。第二范式就是非主属性非部分依赖于主键。
3.3NF:必须先满足第二范式(2NF)。3NF 要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。第三范式就是属性不依赖于其它非主属性。简而言之,最终的目的避免数据重复冗余
简而言之: 1NF 列不可再分,最小原子 (避免重复) ;2NF 主键依赖 (确定唯一); 3NF 消除传递依赖(建立主外键关联 拆分表)
二 SELECT
1.查询列(字段)
(1)部分列
select ename from emp;
(2)所有列
select*from dept;
(3)去除重复 distince
select distince deptno from emp;
(4)别名
select 字段1 (as) 别名1,字段2 (as) 别名2 from 表名 别名; 别名可以是 中文,可以是英文,英文默认大写,想要小写别名前后添加"",""原封不动显示字段添加别名可以使用as,表添加别名不可以使用as
select ename 姓名,sal 薪资 from emp;
select ename "姓 名",sal as "salary" from emp e;
(5)字符串
select 'aaa' "aaa",ename from emp;
a--b || 字符串的拼接
select 'a-'||'-b' from dept;
(6)伪列
不存在的列,构建虚拟的列
select empno, 1*2 as count,'cmj' as name,deptno from emp;
(7)nvl
(值1,值2) 如果值1为null,函数运算的结果是值2,如果值1不为null,结果就是值1
查询所有员工的姓名,奖金
select ename,nvl(comm,1) from emp;
(8)虚表
用于计算表达式,显示单条记录的值
select 1+1 from dual;
2.查询行(记录)
where 过滤行记录条件 ,条件有
a)、= 、 >、 <、 >=、 <=、 !=、 <>、 between and
b)、and 、or、 not、 union、 union all、 intersect 、minus
c)、null :is null、 is not null、 not is null
d)、like :模糊查询 % _ escape('单个字符')
f)、in 、 exists(难点) 及子查询
(1)比较条件
= 、>、 <、 >=、 <=、 !=、 <>
select * from emp where deptno !=20;
select * from emp where deptno <>20;
select * from emp where sal between 800 and 950; --between and是成对出现的
(2)且或非
and、 or、 not
select * from emp where sal>=900 and sal<=950;
(3)null
null不能使用条件判断,只能使用is :
--存在佣金的员工名称
select * from emp where comm is null;
--不存在佣金的员工名称
select * from emp where comm is not null;
select * from emp where not comm is null;
(4)集合操作
Union、Union All、Intersect、Minus
Union,并集(去重) 对两个结果集进行并集操作,不包括重复行同时进行默认规则的排序;
Union All,全集(不去重) 对两个结果集进行并集操作,包括重复行,不进行排序 ;
Intersect,交集(找出重复) 对两个结果集进行交集操作,不包括重复行,同时进行默认规
则的排序;
Minus,差集(减去重复) 对两个结果集进行差操作,不包括重复行,同时进行默认规则的排
序
--查询工资大于1500 或 含有佣金的人员姓名
--union 去除重复行
select ename from emp where sal>1500
union
select ename from emp where comm is not null;
union all 不去除重复行
select ename from emp where sal>1500
union all
select ename from emp where comm is not null;
--查询显示不存在雇员的所有部门号。
select deptno from dept
minus
select distinct deptno from emp
--查询工资大于1500 且 含有佣金的人员姓名
select ename,sal,comm from emp where sal>1500
intersect
select ename,sal,comm from emp where comm is not null;
(5)like:模糊查询
模糊查询,使用通配符:
%: 零个及以上(任意个数的)的字符
_ :一个字符
遇到内容中包含 % _ 使用escape('单个字符')指定转义符
--查询员工姓名中包含字符A的员工信息
select * from emp where ename like '%A%';
--查询员工姓名中包含第二个A的员工名称信息
select * from emp where ename like '_A%';
(6)in 与exists
in相当于使用or的多个等值,定值集合 ,如果存在 子查询,确保 类型相同、字段数为1,如果记录多,效率不高,用于 一些 少量定值判断上:
select * from emp where sal in(900,800)
--子查询(查询中再有查询) in 只能存在一个字段
select * from emp where sal in (select sal from emp e where deptno=10)
--10或30部门的雇员信息
select * from emp where deptno in(10,30);
--部门名称为 SALES 或 ACCOUNTING 的雇员信息
select deptno from dept where dname in('SALES','ACCOUNTING');
select *from emp where deptno in (select deptno from dept where dname in ('SALES',
'ACCOUNTING'));
exists条件为true,存在记录则返回结果,后续不再继续 比较查询,与查询的字段无关与记录有关:
exists(包括 not exists )子句的返回值是一个boolean值。 exists内部有一个子查询语句(select ... from..), 我将其称为exists的内查询语句。其内查询语句返回一个结果集。 exists子句根据其内查询语句的结果集空或者非空,返回一个布尔值。
一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则exists子句返回true,这一行行可作为外查询的结果行,否则不能作为结果。
(7)获取所有行的记录
select * from emp;
select * from emp where 1=1 ;
select * from emp where ename like '%';
3.排序
使用 order by 排序,排序不是真实改变存储结构的顺序,而是获取的集合的顺序。
升序 asc(默认) 降序 desc
多字段: 在前面字段相等时,使用后面的字段排序
空排序: 降序为 desc,注意 null 为最后
--按工资降序
select * from emp order by sal desc;
--null问题
select * from emp order by nvl(comm,0),comm desc;
select * from emp order by comm nulls first;
--查询雇员姓名,年薪 按佣金排序 默认为升序(asc),降序为desc,注意null为最后
select ename,(sal+nvl(comm,0))*12,comm total from emp order by comm desc;
--查询雇员姓名,年薪 按佣金排序 默认为升序(asc),降序为desc,注意null为最后
select ename,(sal+nvl(comm,0))*12,comm total from emp order by comm desc;
--对部门编号为 20 或30的雇员,工资+佣金 进行升序排序,如果相同,则按姓名降序。
--1、查询20、30 雇员
select * from emp where deptno in(20,30);
--2、工资+佣金排序
select ename,sal,comm,sal+nvl(comm,0) c from emp where deptno in(20,30) order by c;
--3、多个字段排序使用, 排序的字段可以使构建出来的虚拟的字段
select ename,sal,comm from emp where deptno in(20,30) order by
sal+nvl(comm,0),ename desc;
4.单行函数
定义:函数分为系统内置函数 自定义函数(后期学习的 plsql 中定义);了解系统内置函数(方法),重点掌握 to_date 、 to_char (字符和日期的转换)
根据函数的返回结果,我们将函数分为单行函数和多行函数
a、单行函数:一条记录返回一个结果
b、多行函数 组函数 聚合函数 (重点) :多条记录 返回一个结果 (重点)
(1)日期函数
日期函数: 注意区分 db数据库时间 ,java应用服务器的时间。以一方为准
oracle以内部数字格式存储日期:年,月,日,小时,分钟,秒
sysdate/current_date 以date类型返回当前的日期
add_months(d,x) 返回加上x月后的日期d的值
LAST_DAY(d) 返回的所在月份的最后一天
months_between(date1,date2) 返回date1和date2之间月的数目
next_day(sysdate,'星期一') 下周星期一
1)当前时间
select current_date from dual where 1=1;
select sysdate from dual where 1=1;
2)修改日期(天数+ - )
两天后的时刻
select sysdate+2 from dual;
3)修改月份
--当前5个月后的时间
select add_months(sysdate,5) from dual;
--雇佣日期 2个月的时间
select ename,hiredate, add_months(hiredate,2) after from emp;
4)月份之差
-雇佣日期 距离现在的 月份数
select ename, months_between(sysdate , hiredate) from emp;
5)最后一天
--返回雇佣日期 当月最后一天的时间
select ename, last_day(hiredate) d from emp;
6)下一个星期的时间
--下一个星期二
select next_day(sysdate, '星期二') from dual;
(2)转换函数(重点)
to_date(c,m) 字符串以指定格式转换为日期
to_char(d,m) 日期以指定格式转换为字符串
select to_date('2017-3-21 18:12:12','yyyy-mm-dd hh24:mi:ss') time from dual;
select to_char(sysdate,'yyyy-mm-dd') from dual;
select to_char(sysdate,'yyyy/mm/dd') from dual;
select to_char(sysdate,'yyyy\mm\dd') from dual;
注意中文的问题
--select to_char(sysdate,'yyyy年mm月dd日') from dual;select
to_char(sysdate,'yyyy"年"mm"月"dd"日"') from dual;
--查询 82的员工信息
select * from emp where hiredate like '%82%' ;
或
select * from emp where to_char(hiredate,'yyyy')='1982';
或
select *from emp
where hiredate between to_date('1982-01-01', 'yyyy-mm-dd') and
to_date('1982-12-31', 'yyyy-mm-dd');
(3)其他函数(保证类型兼容)
--1)、nvl(string1,string2) 如果string1为null,则结果为string2的值
select ename, nvl(null,0) from emp;
select ename, nvl(to_char(comm),'hello') from emp;
--2)、decode(condition,case1,express1,case2 , express2,….casen , expressn, expressionm)
select ename,decode(deptno, 10,'十',20,'二十') from emp;
--3)、case when then else end
例子:
--给所有的员工 涨薪,10-->10% 20-->8% 30 -->15% 其他-->20%
--decode
select ename,sal,deptno,decode(deptno, 10, sal * 1.1, 20, sal * 1.08, 30, sal * 1.15, sal * 1.2) raisesal from emp;
--case when then else end
select ename,sal, deptno, (case deptno when 10 then sal * 1.1 when 20 then sal * 1.08 when 30 then sal * 1.15 else sal * 1.2 end) raisesal from emp;
5.组函数
组函数|多行函数|聚合函数 即多条记录 返回一个结果。我们需要掌握如下几个组函数:
avg 、sum、 min、 max、 count
1)、count :统计记录数 count() -->* 或一个列名
2)、max min: 最大值 最小值
3)、sum:求和
4)、avg:平均值
注意:
1、组函数仅在选择列表和Having子句中有效
2、出现组函数,select 只能有组函数或分组字段
说明:
组信息 与单条记录不能同时查询
组函数 不能用在 where中,能使用的地方 select having
null 不参与运算
(1)Count
count统计所有的员工数
select ename,1 from emp;
select count(1) from emp where 1=1;
null不参与运算
--存在佣金的员工数
--不推荐/不需要
select count(comm) from emp where comm is not null;
--推荐
select count(comm) from emp;
--统计 部门编号30的员工数
select count(1) from emp where deptno=30;
--统计数量过程中 ,可能处理重复
--统计 存在员工的 部门数量
select count(distinct(deptno)) 有人的部门 from emp;
--统计10和20部门一共有多少人
select distinct(count(1)) from emp where deptno in(10,20);
(2)max min
--查询所有员工的 最高薪水 ,最低薪水,员工总数 -->组信息
select max(sal) maxSal , min(sal) minSal , count(1) from emp;
--查询 最高薪水的员工名称 及薪水
--组信息 与单条记录不能同时查询
select max(sal), ename, sal from emp; 错误
select ename, sal from emp where sal=(select max(sal) from emp );
(3)sum求和
-- 查询10部门的所有员工的工资总和
select sum(sal) from emp where deptno=10;
(4)avg 平均
-- 查询工资低于平均工资的员工编号,姓名及工资
select empno, ename,sal from emp where sal<(select avg(sal)from emp);
--查看 高于本部门平均薪水员工姓名
select * from emp e1 where sal>(select avg(sal) from emp e2 where e1.deptno=e2.deptno );
6.分组
分组: group by , 将符合条件的记录 进一步的分组
1)、select 出现分组函数,就不能使用 非分组信息,可以使用 group by 字段
2)、group by字段 可以不出现 select 中 ,反之select 除组函数外的,其他字段必须出现在group by 中
过滤组:having , 过滤组信息 ,表达式 同 where 一致
where :过滤行记录,不能使用组函数, having:过滤组 可以使用组函数
select distinct * | 字段 | 表达式 | 函数 as 别名
from 表 表别名
where 过滤行记录条件
group by 分组字段列表
having 过滤组
order by 字段列表 asc | desc
解析步骤
1)、from 2)、where 3)、group 4)、having 5)、select 6)、order by
--按 部门 查询 平均工资
select avg(sal) from emp group by deptno;
--按 部门岗位 查询 平均工资
select avg(sal) from emp group by deptno,job;
--按 部门 查询 平均工资,且平均工资大于2000的部门编号
--1、先分组 后过滤 (不推荐)
select *from (select deptno, avg(sal) avsal from emp where 1 = 1 group by deptno) where avsal > 2000;
--2、过滤组 ,分组同时 过滤
select avg(sal), deptno from emp group by deptno having avg(sal)>2000;
--查询 最低平均工资的部门编号
--1)、按部门求出平均薪水
select avg(sal) from emp group by deptno;
--2)、找出最低的平均薪水
select min(avg(sal)) from emp group by deptno;
--3)、过滤组
select deptno from emp where 1 = 1 group by deptno
having avg(sal) = (select min(avg(sal)) from emp where 1 = 1 group by deptno);
--查看 高于本部门平均薪水员工姓名
--1、按部门求出平均薪水
--2、关联子查询
select *from emp e where exists (select deptno from (select deptno, avg(sal) avgsal from emp group by deptno) e2
where e.deptno = e2.deptno and e.sal > avgsal);
--另外一种 (推荐)
select *from emp e1 where sal > (select avg(sal) from emp e2 where e2.deptno = e1.deptno);
7.行转列
找出课程名(表头)
select distinct course from tb_student;
数据(行记录) 分组(学生+行转列 decode)
select*from tb_student;
1.行转列 decode
select name,decode(course,'语文',score) 语文,decode(course,'数学',score) 数学,decode(course,'英语',score) 英语 from tb_student;
2.分组
select name,
min(decode(course,'语文',score)) 语文,
max (decode(course,'数学',score)) 数学,
min(decode(course,'英语',score)) 英语
from tb_student group by name;