文章目录
Oracle
一、Oracle体系结构(理解)
1.1 数据库
Oracle数据库是数据的物理存储。这就包括(数据文件ORA 或者DBF、控制文件、联机日志、参数文件)。其实Oracle 数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是Oracle 就只有一个大数据库。
1.2 实例
一个Oracle 实例(Oracle Instance)有一系列的后台进程(Backguound Processes)和内存结构(Memory Structures)组成。一个数据库可以有n 个实例。
1.3 用户
用户是在实例下建立的。不同实例可以建相同的名字的用户(此Oracle中的用户就相当于Mysql里面的database单位)
1.4 表空间
表空间是Oracle对物理数据库上相关数据文件(ORA 或者DBF 文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构。每个数据库至少有一个表空间(称之为system 表空间)。
每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile)。一个数据文件 只能属于一个表空间。
1.5 数据文件(dbf、ora)
数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个
或者多个数据文件中。而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于 一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。
注: 表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。
注意2: 由于oracle 的数据库不是普通的概念,oracle
是有用户和表空间对数据进行管理和存放的。但是表不是有表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同
一个名字的表!这里区分就是用户了!
层次结构图
命令窗口登录操作
在cmd中直接cd进入到D:\oracle\instantclient_12_1的位置,输入sqlplus
然后输入用户名和密码就可以了
quit退出
1.6 创建表空间(理解)
- 表空间? ORACLE 数据库的逻辑单元。 数据库—表空间 一个表空间可以与多个数据文件(物理结构)关联
- 一个数据库下可以建立多个表空间,一个表空间可以建立多个用户、一个用户下可以建立 多个表。
--创建表空间
create tablespace hugong
datafile 'D:\oracle\oracle_workspace\hugong.dbf'
size 100m
autoextend on
next 10m;
--删除表空间
drop tablespace hugong;
- hugong 为表空间名称
- datafile 指定表空间对应的数据文件
- size 后定义的是表空间的初始大小
- autoextend on 自动增长 ,当表空间存储都占满时,自动增长
- next 后指定的是一次自动增长的大小
1.7 用户(理解)
1.7.1 创建用户
--创建用户
create user hugong
identified by hugong
default tablespace hugong;
- identified by 后边是用户的密码
- default tablespace 后边是表空间名称
oracle 数据库与其它数据库产品的区别在于,表和其它的数据库对象都是存储在用户下的
1.7.2 用户赋权限
注: 新创建的用户没有任何权限,登陆后会提示
Oracle 中已存在三个重要的角色:①connect角色 ②resource角色 ③dba角色
1.7.2.1 CONNECT 角色: --是授予最终用户的典型权利,最基本的
ALTER SESSION – 修改会话
CREATE CLUSTER --建立聚簇
CREATE DATABASE LINK – 建立数据库链接
CREATE SEQUENCE – 建立序列
CREATE SESSION – 建立会话
CREATE SYNONYM --建立同义词
CREATE VIEW – 建立视图
1.7.2.2 RESOURCE 角色: 是授予开发人员的(常用)
CREATE CLUSTER – 建立聚簇
CREATE PROCEDURE – 建立过程
CREATE SEQUENCE – 建立序列
CREATE TABLE – 建表
CREATE TRIGGER – 建立触发器
CREATE TYPE – 建立类型
1.7.2.3 DBA 角色:拥有全部特权,是系统最高权限(和system权限差不多)
只有 DBA 才可以创建数据库结构,并且系统权限也需要DBA
授出,且DBA用户可以操作全体用户的任意基表,包括删除
--给hugong用户授予dba角色
grant dba to hugong;
注: 进入 system 用户下给用户赋予 dba权限,否则无法正常登陆
1.8 Oracle数据类型(应用)
序号 | 数据类型 | 描述 |
---|---|---|
1 | Varchar, varchar2 | 表示一个字符串(varchar2更常用) |
2 | NUMBER | NUMBER(n)表示一个整数,长度是n;NUMBER(m,n):表示一个小数,总长度是 m,小数是n,整数是m-n |
3 | DATA | 表示日期类型 |
4 | CLOB | 大对象,表示大文本数据类型,可存 4G |
5 | BLOB | 大对象,表示二进制数据,可存 4G |
二、表的管理(应用)
2.1 建表
- 语法:
Create table 表名(
字段1 数据类型 [default默认值],
字段1 数据类型 [default默认值],
…
字段n 数据类型 [default默认值],
); - 范例:创建person表
--创建person表
create table person(
pid number(20),
pname varchar2(10)
);
2.2 表的删除
语法:DROP TABLE 表名
2.3 表的修改
2.3.1 添加列
--添加一列
alter table person add (gender number(1);
--添加多列
alter table person add (gender number(1),age number(2));
2.3.2 修改列类型
alter table person modify gender char(1);
2.3.3 修改表名称
alter table person rename column gender to sex;
2.3.4 删除表
alter table person drop column age;
三、数据库表数据的CRUD
3.1 select(查询)
-- 查询所有记录
select * from person;
注意:进行增改数据时一定要进行commit操作
因为oracle 的事务对数据库的变更的处理,我们必须做提交事务才能让数据真正的插入到数据库中,在同样在执行完数据库变更的操作后还可以把事务进行回滚,这样就不会插入到数据库。如果事务提交后则不可以再回滚。而在java中有时并不需要进行事务的提交commit,其实是因为在java底层代码中已经帮你进行了事务的提交步骤。
3.2 insert(增加)
-- 添加表中记录
insert into person (pid,pname) values (1,'小华');
commit;
3.3 update(修改)
-- 修改一条记录
update person set pname = '小马' where pid = 1;
commit;
3.4 delete(删除)
- 在删除语句中如果不指定删除条件的话就会删除所有的数据
-- 三个删除
-- 删除表中全部记录
delete from person;
-- 删除表结构
drop table person;
-- 先删除表,再次创建表。效果等同于删除表中全部记录
-- 在数据量大的情况下,尤其在表中带有索引的情况下,该操作的效率高
-- 索引可以提供查询效率,但是会影响增删改效率
truncate table person;
3.5 序列
在很多数据库中都存在一个自动增长的列,如果现在要想在 oracle 中完成自动增长的功能,
则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。
-- 序列不是真的属于任何一张表,但是可以逻辑和表做绑定
-- 序列:默认从1开始,依次递增,主要用来给主键赋值使用
-- dual:虚表,只是为了补全语法,没有任何意义。
create sequence s_person;
select s_person.nextval from dual;
-- 添加表中记录
insert into person (pid,pname) values (s_person.nextval,'小明');
commit;
select * from person;
- 执行结果
四、Scott用户下的表结构(了解)
4.1 scott表的结果图
4.2 scott用户的解锁
-- scott用户,密码tiger
--- 解锁scott用户
alter user scott account unlock;
--- 解锁scott用户的密码【此句也可以用来重置密码】
alter user scott identified by tiger;
五、Oracle中的单行函数(应用)
dual表:虚表,只是为了补全语法,没有任何意义。
5.1 字符函数
接收字符输入返回字符或者数值,dual是伪表
5.1.1 把小写字符变成大写字符
select upper('yes') from dual; --YSE转大写
5.1.2 把大写字符变成小写字符
select lower('YeS') from dual; --yes转小写
5.2 数值函数
- 四舍五入函数:ROUND()
默认情况下ROUND四舍五入取整,可以自己指定保留的位数
select round(32.48) from dual; -- 32
select round(32.48,1) from dual; -- 32.5(保留一位小数)
select round(32.48,-1) from dual; -- 30
select mod(10,3) from dual; -- 取余
5.3 日期函数
Oracle 中提供了很多和日期相关的函数,包括日期的加减,在日期加减时有一些规律日期 – 数字 = 日期
- 日期 + 数字 = 日期
- 日期 – 日期 = 数字
----- 查询出emp表中所有员工入职距离现在几天
select sysdate-e.hiredate from emp e;
----- 算出明天此刻
select sysdate+1 from dual;
----- 查询出emp表中所有员工入职距离现在几个月
select months_between(sysdate,e.hiredate) from emp e;
---- 查询emp表中所有员工入职距离现在几年
select months_between(sysdate,e.hiredate)/12 from emp e;
---- 查询出emp表中所有员工入职距离现在几周
select (sysdate-e.hiredate)/7 from emp e;
5.4 转换函数
5.4.1 TO_CHAR:字符串转换函数
- 在结果中 10 以下的月前面被被补了前导零,可以使用fm 去掉前导
- 在hh前面加上24可以使用24小时制表示时间
---- 日期转字符串
----(hh后面加24代表使用24小时时间,加上fm表示去掉前面的0,比如06:28分就变成了6:28)
select to_char(sysdate,'fm yyyy-mm-dd hh24:mi:ss') from dual;
5.4.2 TO_DATE:日期转换函数
---- 字符串转日期
select to_date(' 2019-10-20 12:35:31','yyyy-mm-dd hh24:mi:ss') from dual;
5.4.3 * 通用函数(开发中常用)
5.4.3.1 空值处理
- 范例:查询所有的雇员的年薪(月薪*12+年终奖)
---- 算出emp表中所有员工的年薪和姓名
---- 奖金里面有null值,如果null值和任意数字做算术运算,结果都是null
select e.ename,e.sal*12+nvl(e.comm,0) from emp e;
5.4.3.2 条件表达式(Decode函数)
5.4.3.2.1 oracle和mysql中通用写法
select e.ename,
(case e.ename
when 'SMITH' then '刘备'
when 'ALLEN' then '张飞'
when 'WARD' then '诸葛孔明'
--else '无名'
end) "中文名"
from emp e;
----练习:判断所有emp中的员工的工资:如果每月工资大于3000的为“高等工资”,
-----每月大于1500小于3000的为中等工资,其余为低等工资
select e.sal,
case
when e.sal>3000 then '高等工资'
when e.sal>1500 then '中等工资'
else '低等工资'
end
from emp e;
----2.oracle中专用的条件表达式的写法
----oracle中除了起别名,其余都用单引号
select e.ename,
decode(e.ename,
'SMITH', '刘备',
'ALLEN', '张飞',
'WARD', '诸葛孔明',
'无名') "中文名"
from emp e;
5.4.3.2.2 Oracle专用写法(decode函数)
- oracle中除了起别名,其余都用单引号
select e.ename,
decode(e.ename,
'SMITH', '刘备',
'ALLEN', '张飞',
'WARD', '诸葛孔明',
'无名') "中文名"
from emp e;
5.4.4 多行函数【聚合函数】:作用于多行,返回一个值
select count(1) from emp; ---查询总数量
select sum(sal) from emp; ---工资总和
select max(sal) from emp; ---最大工资
select min(sal) from emp; ---最低工资
select avg(sal) from emp; ---平均工资
六、分组统计
分组统计需要使用 GROUP BY 来分组
6.1 案例:
---查询出每个部门的平均工资
select e.deptno,avg(e.sal)
from emp e
group by e.deptno;
--- 查询出平均工资高于2000的部门信息
select e.deptno,avg(e.sal) 平均工资
from emp e
group by e.deptno
having avg(e.sal)>2000;
----注意:所有条件都不能使用别名来判断
--比如下面的条件语句也不能使用别名当条件(因为语句执行的优先级where的优先级大于select)
select ename,sal s from emp where s > 2000;
---查询出每个部门工资高于800的员工的平均工资
select e.deptno,avg(e.sal)
from emp e
where e.sal>800
group by e.deptno;
6.2 where和having的使用位置
where是过滤分组前的数据,having是过滤分组后的数据
- 表现形式:where必须在group by之前,having是在group by之后
- 注意:使用where语句时里面不能使用聚合函数
————使用having语句时里面可以使用聚合函数
综合案例:
- 查询出每个部门工资高于800的员工的平均工资然后再查询出平均工资高于2000的部门
select e.deptno,avg(e.sal)
from emp e
where e.sal>800
group by e.deptno
having avg(e.sal)>2000;
七、多表查询(应用)
7.1 多表连接基本查询
7.1.1 笛卡尔积
---笛卡儿积(两种直接相乘就可以了,emp表14条记录,dept表4条记录)
select *
from emp e,dept d;
我们发现产生的记录数是 56 条,我们还会发现emp 表是 14 条,dept 表是4 条,56 正是emp表和dept 表的记录数的乘积,我们称其为笛卡尔积。
如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。
7.1.2 等值连接
----结果是14条记录
select *
from emp e,dept d
where e.deptno = d.deptno;
- 内连接(和等值连接的作用一样)
select *
from emp e inner join dept d
on e.deptno = d.deptno;
7.1.3 外连接(左右连接)
方法:看左边的表是谁然后看条件判断有多少条记录
7.1.3.1 左连接
---查询所有员工信息表,以及对应的部门信息(14条记录)
select *
from emp e left join dept d
on e.deptno = d.deptno;
7.1.3.2 右连接
案例:当我们在做基本连接查询的时候,查询出所有的部门下的员工,我们发现编号为40的部门下没有员工,但是要求把该部门也展示出来,我们发现上面的基本查询是办不到。
---查询所有部门信息,以及该部门对应的员工信息(15条记录:因为有个空部门)
select *
from emp e right join dept d
on e.deptno = d.deptno;
7.1.3.3 Oracle专用:外连接
使用(+)表示左连接或者右连接
select *
from emp e,dept d
where e.deptno(+) = d.deptno; ---此方法与上面的右外连接的作用一样
7.1.3.4 案例一:
---查询出员工姓名,员工领导姓名
select e1.ename 员工姓名,e2.ename 领导姓名
from emp e1,emp e2
where e1.mgr = e2.empno;
---查询出员工姓名,员工部门名称,员工领导名称,员工领导部门名称
select e1.ename,d1.dname,e2.ename,d2.dname
from emp e1,emp e2,dept d1,dept d2
where e1.mgr = e2.empno
and e1.deptno = d1.deptno
and e2.deptno = d2.deptno;
7.1.3.5 综合案例二:查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级
select e1.empno 员工编号,e1.ename 姓名,d.dname 部门名称,
decode(s1.grade,
1,'一级',
2,'二级',
3,'三级',
4,'四级',
5,'五级'
) 工资等级,e2.ename 领导姓名,
decode(s2.grade,
1,'一级',
2,'二级',
3,'三级',
4,'四级',
5,'五级'
) 工资等级
from emp e1,emp e2,dept d,salgrade s1,salgrade s2
where e1.mgr = e2.empno
and e1.deptno = d.deptno
and e1.sal between s1.losal and s1.hisal
and e2.sal between s2.losal and s2.hisal;
- 执行结果
八、*子查询(应用)
子查询:在一个查询的内部还包括另一个查询,则此查询称为子查询
- 一般比较复杂的查询语句先写好框架:select(分行) from(分行) where(分行)
8.1 子查询返回一个值
等值运算时尽量用in关键字,不要用”=“,因为很可能值不只有一个与之对应
--- 查询出工资和SCOTT一样的员工信息
select * from emp where sal in
(select sal from emp where ename='SCOTT');
8.2 子查询返回一个集合
--- 查询出工资和10号部门任意员工一样的员工信息
select * from emp where sal in
(select sal from emp where deptno='10');
8.3 子查询返回一个表
案例:查询出每个部门最低工资,和最低工资号员工姓名,和该员工所在部门名称
----1.查询出每个部门的最低工资(按组分)
select deptno,min(sal) minsal
from emp
group by deptno;
----2.再进行整个数据,子查询
select mins.minsal,d.deptno,e.ename,d.dname
from emp e,dept d,(select deptno,min(sal) minsal
from emp
group by deptno)mins
where e.deptno = d.deptno
and e.deptno = mins.deptno
and e.sal = mins.minsal;
九、Rownum与分页查询(应用)
rownum行号:当我们做select操作的时候每查询出一行记录,就会在该行上加上一个行号
行号从1开始,一次递增,不能跳着走
- order by 顺序排列,加上desc表示倒叙排列
--- 将员工的工资按照倒叙排列
例如:select e.* from emp e order by e.sal desc;
9.1 关于rownum的使用
- 案例:查询员工信息表的前三名
如果按照正常思路写的话结果与预想的不一样
select rownum,e.* from emp e where rownum < 4 order by e.sal desc;
- 因为如果直接进行查询会有rownum的默认排序
select rownum,e.* from emp e;
2. 如果按照order by这种有序排列会将原始的初始rownum数据打乱
---------排序操作会影响rownum的顺序
select rownum,e.* from emp e order by e.sal desc;
3. 所以需要在外面套用一层rownum进行查询,使用外面的
select rownum rn,t.* from
(select rownum,e.* from emp e order by e.sal desc) t where rownum < 4;
9.2 **rownum常用固定格式写法
rownum不支持大于号,只支持小于号,如果想实现分页查询,有大于号判断就用如下方法实现
案例:emp表工资倒叙排列后,每页五条记录,查询第二页
select * from (
select rownum rn,t.* from(
select * from emp order by emp.sal desc
) t where rownum < 11
)where rn > 5;