数据库
一,数据库简介
1.数据库的起源: 随着互联网时代的到来,需要持久化数据呈现井喷式发展,常规的 io操作虽然 可以满足持久化的需求,但是,对于持久化的目的,对数据的操纵,显然力不从心, 且操作的复杂度很大,不利于大规模的发展,审时度势,数据库应运而生。
2.数据库的定义:数据库(Database)是按照数据结构来组织、存储和管理数据的仓库;随着信息 技术和市场的发展,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各 种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够 进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。
数据库现在已经成为数据管理的重要技术,也是计算机的重要分支。由于数据 库具有数据结构化,最低冗余度、较高的程序与数据独立性,易于扩展、易于编制应 用程序等优点,较大的信息系统都是建立在数据库设计之上的。数据库的运用从一般 管理扩大到计算机辅助技术、人工智能以及科技计算等领域。
随着数据库技术的发展,计算机技术也随着得到了很大的发展,数据库为我们 提供了可以快速存储以及检索的便利,它也为近几年软件可以如此普及贡献不小的力 量
3.常用的数据库有:MySQL,Oracle,DB2
4. 数据库管理系统(Database Management System)是一种操纵和管理数据库的大 型软件,用于建立、使用和维护数据库,简称 DBMS。它对数据库进行统一的管理和 控制,以保证数据库的安全性和完整性。用户通过 DBMS访问数据库中的数据,数据 库管理员也通过dbms进行数据库的维护工作。它可使多个应用程序和用户用不同的 方法在同时或不同时刻去建立,修改和询问数据库。大部分 DBMS提供数据定义语言 DDL(Data Definition Language)和数据操作语言 DML(Data Manipulation Language),供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除 等操作。
根据存储模型可将数据库划分为关系型数据库和非关系型数据库。关系型数据库, 是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库 中的数据。简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是 由二维表及其之间的联系所组成的一个数据组织。标准数据查询语言SQL 就是一种 基于关系数据库的语言,这种语言执行对关系数据库中数据的检索和操作。
当前主流的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。
Oracle Database,又名Oracle RDBMS,或简称 Oracle。是甲骨文公司的一款 关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说 Oracle数 据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功 能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的 适应高吞吐 量的数据库解决方案。
二、SQL 语言介绍
SQL(Structured Query Language)为数据库的语言,在1974年由Boyce【博伊 斯】和Chamberlin【钱伯林】提出的一种介于关系代数与关系演算之间的结构化查询 语言,是一个通用的、功能极强的关系型数据库语言。它包含三部分:
部分操作命令:
1.表
(1)、定义:、表是从属于用户的 ,查询表(用户名.表名),当前用户查询自己的表时,用户名. 可以省略,其他用户查询 别的用户表 ,不能省略,同时必须存在权限。、表是逻辑表(概念表),不是物理表 块(8k) --->区(连续块)-->段(连续区) -->表(多个段) ,数据段不全是表,表一定是数据段。还 有其他段:如索引段。
(2)、表结构:
2. Scott用户表
(1)、四种表
(2)、查看表结构
(3)、用户表说明
3、三范式
在设计数据库时,存在行业的标准,这个标准也称为条件,即范式 Normal Form。一般遵循三个条件即可,也就是”三范式”(3NF)。
1NF:是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值, 即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能 需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。 在第一范式(1NF)中表的每一行只包含一个实例的信息。
2NF:是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第 一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。 为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。如 emp表中加上了员 工编号(empno)列,因为每个员工的员工编号是唯一的,因此每个员工可以被唯一区分。 这个唯一属性列被称为主关键字或主键、主码。同时要求实体的属性完全依赖于主关键字。 所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主 关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。 为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。即第二范式就是非主属性非部分依赖于主键。
3NF:必须先满足第二范式(2NF)。3NF要求一个数据库表中不包含已在其它表中已包 含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(deptno)、 部门名称、地址等信息。那么员工信息表(emp)中列出部门编号后就不能再将部门名称、部 门地址等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。即第三范式就是属性不依赖于其它非主属性。
4. SELECT使用
(1)、基本操作
--sql中的注释
--DQL 查询语句
--select *|字段名1,字段名2... from 表名;
--查询某个表中的所有数据
--select * from 表名
select * from emp;
--查询所有员工的姓名
--select 字段名 from 表名;
select ename from emp;
--查询所有员工的姓名,员工编号,上级编号
--查询的数据: ename,empno,mgr
--数据来源: emp雇员表
--查询的条件:
select ename, empno, mgr from emp;
--查询所有员工的部门编号
--查询的数据: deptno
--来源: dept|emp
select deptno from dept;
select deptno from emp;
--所有有员工存在的部门的部门编号
--查询的数据: deptno
--来源: emp
--去重 distinct
select distinct deptno from emp;
select distinct ename,deptno from emp
--表达式 结果字段的名字为表达式的名字 值为表达式计算的结果-->计算器
select 1+1 from emp;
select distinct 123*456 from emp;
--别名 select 字段1 as 别名,字段2 as 别名, 字段3 别名.. from 表名 别名;
--别名如果是英文默认大写,如果想要原样使用|中文带空格,在别名的前后""
select distinct 123+456 as "get Sum" from dept;
select distinct 123+456 "求 和" from dept d;
--''代表字符串 ""原样输出 结果字段名和值原样字符串输出
select '哈哈' "123" from emp;
--表达式|字符串都是伪列:不是表中真是存在的字段
--字符串的拼接 ||
select 'a-'||'-b' from dual;
--查询所有员工的姓名添加同一前缀 尚学堂
select '尚学堂'||ename "学生姓名" from emp;
--虚表: oracle中不是真是存在的表,其中没有任何数据 dual
select sysdate from dual;
--null
--查询所有员工的员工姓名和奖金
select ename,comm from emp;
--null与数字进行运算,结果为null
--在所有员工原奖金基础上+1
select ename, comm, comm+1 from emp;
--null与字符串运算结果不会改变原串
select ename, comm, comm||'1' from emp;
--处理null值 nvl(字段,值2) 如果字段值1位null,给你值2,如果值1不为null,给你值1
select ename 姓名, comm 奖金, nvl(comm,0)+1 "+1后的奖金" from emp;
--一节结尾小练习
--查询所有员工的名字, 工种, 年薪(不带奖金)
select ename, job, sal*12 from emp;
--查询所有员工的名字,工种,年薪(带12月奖金的)
select ename, job, (sal+nvl(comm,0))*12 from emp;
--查询所有员工的名字, 工种, 年薪(带一次奖金的)
select ename, job, sal*12+nvl(comm,0) from emp;
--条件查询
--select *|字段1,字段2.. from 表名 where 行过滤条件;
--求20部门所有员工信息
select * from emp where deptno = 20;
--求30部门的所有员工的员工名称,和部门编号
select ename, deptno from emp where deptno =30;
--执行顺序 from---where---select
-- = 、 >、 <、 >=、 <=、 !=、 <>、
--所有员工中薪资>800
select * from emp where sal>800;
--SMITH查询斯密斯的信息
select * from emp where ename='SMITH';
--求除了SMITH以外的所有员工信息
select * from emp where ename != 'SMITH';
select * from emp where ename <> 'SMITH';
select * from emp where not ename = 'SMITH';
--and 、or、 not , between and
--求薪资在1500~2500之间的员工信息
select * from emp where sal >=1500 and sal<=2500;
select * from emp where sal between 1500 and 2500; --是>=<=
--求薪资>1500并且是30部门的员工名称,部门标号,薪资
select ename,deptno,sal from emp where sal>=1500 and deptno=30;
--求薪资>1500或者30部门的员工名称,部门标号,薪资
select ename,deptno,sal from emp where sal>=1500 or deptno=30;
--求除了薪资>1500和30部门的员工名称,部门标号,薪资
select ename,deptno,sal from emp where not sal>=1500 and not deptno=30;
--select ename,deptno,sal from emp where not(sal>=1500 and deptno=30);
select ename,deptno,sal from emp where not(sal>=1500 or deptno=30);
----查询 岗位 为 CLERK 且部门编号为 20的员工名称 部门编号,工资
select ename,deptno,sal from emp where job='CLERK' and deptno=20;
--求奖金为null的人
select * from emp where comm is null;
--求有奖金的人
select * from emp where comm is not null;
select * from emp where not comm is null;
--select * from emp where comm not is null; 错误事例
--集合操作
--求薪资>1500或者30部门的员工名称,部门标号,薪资
select * from emp where sal>=1500;
select * from emp where deptno=30;
(2)、集合操作
--集合操作
--求薪资>1500或者30部门的员工名称,部门标号,薪资
select * from emp where sal>=1500
Union
select * from emp where deptno=30;
--l Union All,全集(不去重)
select * from emp where sal>=1500
Union All
select * from emp where deptno=30;
-求没有员工在的部门标号
select deptno from dept
Minus
select distinct deptno from emp;
--like 模糊查询 %任意个任意字符 _任意一个字符
--姓名以A开头的所有员工信息
select * from emp where ename like 'A%';
--使用模糊匹配做精确匹配
select * from emp where ename like 'JONES';
--姓名中第二个字符为A的所有员工姓名
select ename from emp where ename like '_A%';
--姓名以H结尾的所有员工信息
select ename from emp where ename like '%H';
--测试数据
insert into emp(empno,ename,sal) values(1000,'t_%test',8989);
insert into emp(empno,ename,sal) values(1200,'t_tes%t',8000);
--查找名字中带有%的用户
select * from emp where ename like '%A%';
select * from emp where ename like '%C%%' escape('C'); --任意指定转义字符,需要使用escape() 中说明
--事务
commit;
rollback;
--in 匹配后面结果集中的任意一个数据,无法做区间判断
--查询薪资为 1500 2000 2500 5000的员工信息
select * from emp where sal=1500 or sal = 2000 or sal=2500 or sal=5000;
select * from emp where sal in (1500,2000,2500,5000);
--查找 KING 和 SMITH 两个员工的信息
select * from emp where ename = 'KING' or ename = 'SMITH';
select * from emp where ename in ('KING','SMITH');
--查询 在SALES he ACCOUNTING 的所有员工信息
--查询的数据:*
--来源:emp
--条件: 1)查询SALES he ACCOUNTING的部门编号 2)根据上一步查询的部门标号在emp中查询满足条件的数据
select deptno from dept where dname in('SALES','ACCOUNTING'); --10,30
select * from emp where deptno in(10,30);
--子查询 查询语句中嵌套查询语句
select *
from emp
where deptno in
(select deptno from dept where dname in ('SALES', 'ACCOUNTING'));
--查询薪资等级为2的员工信息
--查询的数据:*
--来源:emp
--条件: 薪资等级为2
select losal from salgrade where grade =2; --1201
select hisal from salgrade where grade =2; --1400
select *
from emp
where sal between (select losal from salgrade where grade = 2) and
(select hisal from salgrade where grade = 2);
--查询 销售部(SALES) 中 工资大于1500的员工信息
--查询的数据:*
--来源:emp
--条件: 销售部(SALES) sal>1500
select *
from emp
where sal > 1500
and deptno in (select deptno from dept where dname = 'SALES');
--查询工资比SMITH高的同一部门的员工信息
--查询的数据:*
--来源:emp
--条件: deptno是 'SMITH'的部门 sal>'SMITH'的薪资
select *
from emp
where deptno in (select deptno from emp where ename = 'SMITH')
and sal > (select sal from emp where ename = 'SMITH');
select ename,deptno,sal from (select *
from emp
where deptno in (select deptno from emp where ename = 'SMITH')
and sal > (select sal from emp where ename = 'SMITH'));
--exists 存在即保留 存在即合法
select * from emp where exists (select * from dept where dname='SALES');
select *
from emp
where exists (select deptno, dname
from dept
where dname in ('SALES', 'ACCOUNTING'));
--销售部和财务部所有员工信息
select *
from emp
where exists (select deptno, dname
from dept
where dname in ('SALES', 'ACCOUNTING')
and emp.deptno = dept.deptno);
select *
from emp e
where exists (select deptno, dname
from dept d
where dname in ('SALES', 'ACCOUNTING')
and e.deptno = d.deptno);
--除了销售部和财务部部门的所有员工信息
select *
from emp e
where exists (select deptno, dname
from dept d
where dname in ('SALES', 'ACCOUNTING')
and e.deptno != d.deptno);
--获取所有行记录
select * from emp;
select * from emp where 1=1;
--排序 order by desc 降序 asc升序
--select * from 表名 where 行过滤条件 order by 排序字段; --默认升序
--from--where--select--order by
select * from emp order by sal asc;
--根据薪资进行升序排序,薪资相同的根据员工编号进行降序排序
select * from emp order by sal asc,empno desc;
--根据员工的奖金进行降序排序 nulls first nulls last
select * from emp where deptno=30 order by comm desc nulls first;
(3)函数
--当前日期
select sysdate from dual;
select current_date from dual;
--2天后的日期
select sysdate+2 from dual;
--员工入职后3天的日期
select hiredate,hiredate-3 from emp;
--员工的转正日期
select hiredate 入职日期,hiredate+30*3 转正日期 from emp;
--add_months(d,x)
select hiredate 入职日期,add_months(hiredate,3) 转正日期 from emp;
select hiredate 入职日期,add_months(hiredate,-1) 转正日期 from emp;
--LAST_DAY(d) 返回的所在月份的最后一天
--当前月份最后一个的日期
select last_day(sysdate) from dual;
--入职月份的最后一天
select last_day(hiredate) from emp;
-- months_between(date1,date2) 返回date1和date2之间月的数
--员工入职时间
select months_between(sysdate,hiredate) from emp; --月
--next_day(sysdate,'星期一') 下周星期一
--下个周一
select next_day(sysdate,'星期一') from dual;
--下个周四 即将要过的下一个周四
select next_day(sysdate,'星期四') from dual;
--to_date(c,m) à 字符串以指定格式转换为日期
select to_date('2018-05-15 2:38:33','yyyy-mm-dd hh12:mi:ss') from dual;
select to_date('2018年05月15日 2:38:33','yyyy-mm-dd hh12:mi:ss') from dual;
--to_char(d,m) à 日期以指定格式转换为字符串
--组函数 count() sum() max() min() avg()
--count(字段|*|1)
--计算所有员工的个数
select count(empno) from emp;
select count(*) from emp;
select count(1) from emp;
--求有员工存在的部门个数
select count(distinct deptno) from emp;
select count(distinct 1) from emp;
select count(deptno) from dept where deptno in(select distinct deptno from emp);
--求一个公司这个月的薪资开销
select sum(sal) from emp;
select sum(sal) from emp where deptno=20;
--求公司最高薪资
select max(sal) from emp;
--求公司最低薪资
select min(sal),max(sal),ename from emp;
select min(sal) from emp;
--求公司薪资最低的人和薪资
select ename, sal from emp where sal = (select min(sal) from emp);
--求30部门的平均薪资
select avg(sal) from emp where deptno=30;
--求薪资高于平均薪资的员工姓名
select ename,sal from emp where sal>(select avg(sal) from emp);
-- 查出比本部门平均工资高的员工信息
--查询10部门的平均薪资
select avg(sal) from emp where deptno=10;
select *
from emp e1
where sal > (select avg(sal) from emp e2 where e2.deptno = e1.deptno)
--分组 group by 分组字段
--select *|字段.. from 表名 where 行过滤条件 group by 分组字段 having 组过滤信息 order by 排序字段;
--执行流程:from--where--group by--having--select--order by
--select ename en from emp where en='SMITH';
select deptno from emp group by deptno;
-- 找出20部门和30部门的最高工资
select max(sal) from emp group by deptno having deptno in(20,30);
-- 求出每个部门的平均工资
select avg(sal) from emp group by deptno;
-- 求出每个部门员工工资高于1000的的平均工资
select avg(sal) from emp where sal>1000 group by deptno
-- 求出10和20部门部门的哪些工资高于1000的员工的平均工资
select avg(sal) from emp where sal>1000 group by deptno having deptno in(20,30);
select avg(sal) from emp where sal>1000 and deptno in(20,30) group by deptno;
-- 求出平均工资高于2000的部门编号和平均工资
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
--查询 最低平均工资的部门编号
--先查出最低的部门平均薪资
select min(avg(sal)) from emp group by deptno;
select deptno
from emp
group by deptno
having avg(sal) = (select min(avg(sal)) from emp group by deptno);
----查看 高于本部门平均薪水员工姓名
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);
---- 统计每个部门的员工数,和部门编号
-- 查询每个工种的最高工资以及工种
---- 查询平均工资在1500到2000之间的部门平均工资和部门编号
select min(avg(sal)) from emp group by deptno;
select deptno
from emp
group by deptno
having avg(sal) = (select min(avg(sal)) from emp group by deptno);
----查看 高于本部门平均薪水员工姓名
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 deptno,count(1) from emp group by deptno;
-- 查询每个工种的最高工资以及工种
select job,max(sal) from emp group by job;
---- 查询平均工资在1500到2000之间的部门平均工资和部门编号
select avg(sal),deptno from emp group by deptno having avg(sal) between 1500 and 2000 ;
--decode(字段,字段值1,值2,字段值2,值3..,默认值)根据某个字段进行判断
--打印所用的部门名称,如果10,添加一个伪列,显示对应部门的大写名称
select deptno,decode(deptno,10,'十',20,'二十',30,'三十','其他') from dept;
--给20部门的员工涨薪10%,打印员工信息
select ename,deptno,sal,decode(deptno,20,sal*1.1,sal) 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;
--测试数据
create table tb_student(
id number(4) ,
name varchar2(20),
course varchar2(20),
score number(5,2)
);
insert into tb_student values(1,'张三','语文',81);
insert into tb_student values(2,'张三','数学',75);
insert into tb_student values(3,'李四','语文',81);
insert into tb_student values(4,'李四','数学',90);
insert into tb_student values(5,'王五','语文',81);
insert into tb_student values(6,'王五','数学',100);
insert into tb_student values(7,'王五','英语',90);
commit;
drop table tb_student cascade constraints;
select * from tb_student;
--使用一条sql语句,查询每门课都大于80分的学生姓名
select name
from tb_student
group by name
having min(score) > 80 and count(course) = (select count(distinct course) from tb_student);
--数据 : name
--来源 : tb_student
--条件 : 每门课程(这个人所有课程最小分数)>80分 课程个数=3(select count(distinct course) from tb_student)
--查询课程数
select count(distinct course) from tb_student;
--求每个人课程最小分数
select min(score) from tb_student group by name;
--行转列
select name , from tb_student group by name;