Oracle数据库---92/99语法、视图、表连接和表设计、、索引、序列
学习目标
1、92语法
当我们想要的数据来自于多张表时就需要使用表连接。
- 在表连接过程中,如果想某一张表中的所有数据无论是否满足连接条件都显示,可以把这张表设置为主表;
- 主表:在连接位置,主表对面的连接条件有“(+)”,在外连接中主表的数据可以全部展示。
- 外链接
- 左外连接 : 主表在逗号左边就是左连接
- 右外连接 : 主表在逗号右边就是右连接
- 等值连接和非等值连接
注意:
- 表连接后,当使用的字段是多个表共同的字段时需要指明字段的出处
1.1、等值连接(在笛卡尔积的基础上取条件列相同的值)
--查询所有员工的员工信息和所在的部门信息
select * from emp e,dept d where e.deptno = d.deptno;
--30部门和20部门的员工信息与所在部门信息
select * from emp e,dept d where e.deptno = d.deptno and e.deptno in(20,30);
--查询员工信息与员工薪资等级信息,所在部门信息
select *
from emp e, dept d, salgrade s
where sal between s.losal and s.hisal
and e.deptno = d.deptno;
1.2、非等值连接(>、<、!=、<>、between and):
--查询员工信息与员工的薪资等级信息
select * from emp e,salgrade s where e.sal between s.losal and s.hisal;
--查询员工信息与员工薪资等级信息,所在部门信息
select *
from emp e, dept d, salgrade s
where sal between s.losal and s.hisal
and e.deptno = d.deptno;
1.3、自连接:
--查询经理人的编号、姓名、工资、部门编号
select e1.eno,e1.ename,e1.sal,e1.deptno from emp e1,emp e2 where e1.mgr=e2.empno;
1.4、外连接实例:
--查询有上级的员工的信息以及上级经理人信息
select * from emp e1,emp e2 where e1.empno = e2.mgr;--没有上级的King被自动过滤掉了
--查所有员工的信息以及上级经理人信息
--员工表为主表
select * from emp e1,emp e2 where e1.mgr = e2.empno(+);--左外连接
select * from emp e1,emp e2 where e1.mgr(+) = e2.empno;--右外连接
2、99语法
表连接方式:
-
交叉连接 cross join —>笛卡尔积
-
自然连接(主外键、同名列) natural join -->等值连接
-
join using连接(同名列) -->等值连接(在要连接的表之间存在多个字段相同时使用)
-
[inner] join on 连接 -->等值连接、非等值、自连接 (可以实现一切连接方式,但关系列必须区分)
-
left|right [outer] join on|using(同名列) -->左(右)外连接
-
full join on|using(字段名) -->全连接,满足直接匹配,不满足 相互补充null ,确保 所有表的记录 都至少出现一次
注意:
- 使用on时可以是等值连接,也可以是非等值连接(关键看on后面的连接条件),使用using一定是等值连接
2.1、cross join 笛卡尔积(对乘)
select * from emp,dept;
select *
from (select * from emp where deptno in 30)
cross join (select * from dept where deptno in 20);
2.2、natural join自然连接
--自然连接 natural join 自动根据同名字段|主外键关系
select ename,sal,deptno from emp natural join dept; --同名字段不能指明出
2.3、using连接
当存储在多个同名字段时,可以指明使用哪个字段进行连接,且只能做等值连接。
--join using(等值连接字段名) 当存在多个同名字段,可以指明使用哪一个做等值连接
select ename,sal,deptno from emp join dept using(deptno);
2.4、do连接
使用do可以做任意连接(等值或非等值)。
--使用on实现等值连接
select * from emp e join dept d on e.deptno = d.deptno;
----------------------使用on实现非等值连接--------------------
--查询员工薪资等级
select * from emp e join salgrade s on e.sal between s.lowsal and hisal;
-- 查询非20部门并且薪资>1500的员工信息以及薪资等级信息(使用99中的join on 连接),并且按薪水降序
select *
from emp e
join salgrade s
on e.sal between s.losal and s.hisal
where e.deptno != 20
and sal > 1500
order by sal desc;
--查询30部门的员工信息,所在部门信息,薪资等级情况,以及上级经理人信息
select *
from emp e1
join dept d
on e1.deptno = d.deptno
join salgrade s
on sal between losal and hisal
join emp e2
on e1.mgr = e2.empno
where deptno = 30;
2.5、外连接
想要某张表中不满足连接条件的数据都显示,把这张表定义为主表,不满足的部分用null补齐。
- 左外连接,left join on|using
- 右外连接,right join on|using
select * from emp e1 left join emp e2 on e1.mgr=e2.empno;
select * from emp e1 right join emp e2 on e1.mgr=e2.empno;
2.6、全连接
连接的表都作为主表。是左连接和右连接集合的并集。
select * from emp e1 full join emp e2 on e1.mgr=e2.empno;
3、视图
- 当某个结果集被反复使用时就可以考虑添加视图;
- 介于表和结果集之间的就是试图,其实也是结果集,但是这个结果集可以被存储,以后可以查询试图中的数据;
- 最大的优点:就是封装查询到的结果集,简化sql;
- 合理使用试图,不要滥用
语法:create or replace view 试图名字 as 结果集 with read only;
--创建视图
create or replace view vw_emp as select empno,ename,sal,deptno from emp where deptno !=10 with read only;
--查询视图中的数据
select * from vw_emp;
--删除试图
drop view vw_emp;
--如果权限不够
--切换管理员sys用户
--授权: grant dba to scott;
--回收: revoke dba from scott;
习题:
--查询每个部门中所有经理的人的平均薪资,以部门为单位,求出最低平均薪资的那个部门的部门名称
---------------------------- 不使用视图 ----------------------------
--步骤1:计算各个部门经理的平均工资
select e2.deptno num, avg(e2.sal) avg_sal
from emp e1
join emp e2
on e1.mgr = e2.empno
group by e2.deptno;
--步骤2:最低平均工资
select min(avg(e2.sal))
from emp e1
join emp e2
on e1.mgr = e2.empno
group by e2.deptno;
--获得部门名称
select num,t2.dname
from (select e2.deptno num, avg(e2.sal) avg_sal
from emp e1
join emp e2
on e1.mgr = e2.empno
group by e2.deptno) t1 join dept t2 on t1.num = t2.deptno
where avg_sal = (select min(avg(e2.sal))
from emp e1
join emp e2
on e1.mgr = e2.empno
group by e2.deptno);
---------------------------- 使用视图 ----------------------------
--创建视图
create or replace view vw_avgsal as select e2.deptno num ,avg(e2.sal) avg_sal from emp e1 join emp e2 on e1.mgr=e2.empno group by e2.deptno;
--查找最小平均值
select min(avg_sal) from vw_avgsal;
--获得部门名称
select deptno, dname
from vw_avgsal v
join dept d
on v.num = d.deptno
where avg_sal = (select min(avg_sal) from vw_avgsal);
4、索引
索引是数据库的对象之一,用于优化数据库的查询。
特点:
- 在对大量数据进行查询的时候效率较高,数据量较少时反而效率低。
- 索引的创建与删除完全不影响字段的使用。
- 在唯一字段或数据重复量不大的字段可以使用索引。
- Oracle中主动为主键设置索引。
语法:
创建索引:create index 索引名 on表名 (字段列表…)
删除索引:–drop index 索引名
--创建索引
create index index_sal on emp(sal);
--删除
drop index index_sal;
5、设计表
- 设计表时要满足三范式。
- 表之间的关系有:一对一、一对多、多对多
创建表的约束问题:
- 创建字段的时候给出字段约束;
- 在创建表的结构与结束之间给出约束;
- 创建表结束后追加约束。
约束的添加:
- 物理约束:在表上添加约束
- 逻辑约束:在java代码层面添加检查操作,符合条件的在存入数据库,这样灵活性更高。
约束分类:
-
主键约束:关键字primary key
-
外键约束:foreign key(字段名)
-
非空约束:not null
-
检查约束:check(检查条件)
-
唯一约束:unique(字段名)
-
默认值:default(默认值)
5.1、创建表的时候给出约束条件:
create table sxt_student(
sid number(5) constraints pk_sxt_student_sid primary key,--主键约束,给约束起名字
sname varchar2(15) not null,--非空约束
sage number(3) check(sage between 0 and 150),--检查约束
ssex varchar2(3 char) check(ssex in('女','男')),--检查约束
hiredate date default(sysdate),--默认值
cid number(5) constraints fk_sxt_student_cid references sxt_class(cid)--添加外键
)
5.2、创建字段后创建表结束前给出约束:
create table sxt_class(
cid number(5),
cname varchar2(15),
--添加约束(必须给出约束名)
constraints pk_sxt_class_cid primary key(cid)
)
5.3、创建表后添加约束:
--后续追加约束(必须给出约束名)
alter table sxt_student add constraints pk_sgender check(sgender in('男','女'));
5.4、删除约束:
--删除约束
alter table sxt_student drop constraints sxt_student_sname_notnull;
5.5、添加数据:
--逐个字段添加(也可以同时添加多个字段)
insert into sxt_class(cid) values(1002);
--一次性添加所有字段
insert into sxt_class values(1001,'java36');
insert into sxt_student values(01,'张三',18,'男',sysdate,1001);
5.6、删除数据
- 从表中的数据可以直接删除;
- 删除主表数据:
- 主键没有被引用可以直接删除
- 被引用了:
- 默认 先删除从表引用的数据,再删除被引用的主表数据
- 添加外键约束时,on delete set null 删除主表数据的同时,从表引用字段设置为null
- 添加外键约束时,on delete cascade 删除主表数据的同时,级联删除从表中引用了该主键作为外键的从表记录。
-- 删除表数据
delete from sxt_class where cid=1002;
5.7、删除表
-
默认先删除从表再删除主表
-
删除的主表中没有字段作为其他表的外键时可以直接删除;
-
级联:删除主表的同时删除从表中对应的外键约束
--简单删除删除
drop table sxt_student;
--cascade constraints删除表的同时级联删除约束
drop table sxt_class cascade constraints;
5.8、追加外键约束
- 级联:删除主表时,使用该主表中的主键作为外键的从表数据一并删除,使用关键字“on delete cascade”
- 删除主表时,使用该主表中的主键作为外键的从表数据将该外键置为null,使用关键字“on delete set null”
--追加外键约束1
alter table sxt_student add constraints fk_sxt_student_cid_class foreign key(cid) references sxt_class(cid) on delete cascade;
--追加外键约束2
alter table sxt_student add constraints fk_sxt_student_cid_class foreign key(cid) references sxt_class(cid) on delete set null;
5.9、操作约束
查看某个用户的约束:
select constraint_name, constraint_type
from user_constraints
where owner = upper('scott');
查看表的约束:
select constraint_name,constraint_type
from user_constraints
where table_name=upper('tb_user');
查看字段名+约束:
select constraint_name, column_name
from user_cons_columns
where table_name = upper('tb_user');
约束的禁用和启用:
ALTER TABLE tb_user disable constraint nn_user_name;
ALTER TABLE tb_user enable constraint nn_user_name;
删除约束:
alter table tb_user drop constraint uq_user_email cascade;
修改约束:
--非空
alter table tb_user modify (username varchar2(20));
--默认
alter table tb_user modify (age default null);
6、表的其他操作
6.1、修改表结构
1、修改表名 :rename to
2、修改列名: alter table 表名 rename column to
3、修改类型: alter table 表名 modify(字段 类型)
4、修改约束: 先删除 后添加
5、添加列: alter table 表名 add 字段 类型
6、删除列:alter table 表名 drop column 字段
--修改表名
rename tb_txt to tb_txt_new;
--修改列名
alter table tb_txt_new rename column txtid to tid;
--修改类型
alter table tb_txt_new modify(tid varchar2(20));
--添加列
alter table tb_txt_new add col varchar2(30);
--删除列
alter table tb_txt_new drop column col;
select * from tb_txt_new;
6.2、截断数据
truncate: 截断所有的数据 ,如果截断的是主表,结构不能存在外键关联,截断数据同时从表的结构上进行检查。
create table emp_his as select * from emp where 1=1;
select * from emp_his;
--截断所有的数据
truncate table emp_his;
--不能截断: truncate table dept;
6.3、序列sequence
使用工具|程序管理流水号(如主键),序列在创建时没有与表关联 ,在操作数据时才会与表关联。如果不使用序列工具,主键可能出现跳号的问题,或者每次增加一条新的记录时还需要查看表中当前主键编码到什么位置了,这样比较麻烦,这时就可以使用序列(sequence)自动完成主键的编号。
- currval :当前值
- nextval:下个值
创建:
create sequence 序列名 start with 起始值 increment by 步进;
使用:
create sequence seq_tb_user start with 2 increment by 2;
drop sequence seq_tb_user;
select seq_tb_user.nextval from dual;
select seq_tb_user.currval from dual
删除:
drop sequence 序列名