Oracle数据库
数据库对象和多表查询
■ 高级查询 多表查询
如果查询两张表,并且没有定义连接条件,那么查询的结果集是两表相乘的结果,这样的情况称之为笛卡尔乘积
笛卡尔乘积会产生很多行结果。比如,第一张表的行数为50行,第二张表为100行,那么笛卡尔乘积产生的结果为5000行。因为第一张表的每条记录会对应第二张表的100条记录,即50*100=5000
例如
SELECT e.empno, e.ename,d.deptno
FROM emp e,dept d;
此时雇员表emp有14条记录,dept有4条记录,查询后有56条记录,所有为了消除笛卡尔乘积,我们在做多表查询的时候,要加上连接条件。
■ 连接条件和连接类型
常见的有两类连接条件
等值连接:一般使用等于号(=)操作符
非等值连接:使用除了等于以外的运算符,一般使用<>、>、<、<=、>=、LIKE、IN、BETWEEN等运算符
常见的三种连接类型
内连接
内连接返回的行只有满足连接条件才会返回。如果连接条件的列中有NULL值,那么该行则不会返回
Inner join
外连接
外连接返回的行满足连接条件,也包括在连接条件的列包含空值的行
Left outer join,right outer join
自连接
连接的表为同一张表
自连接:
例如要求查询出员工及他的上级。
SELECT e.ename AS 员工,b.ename AS 领导 FROM emp e LEFT JOIN emp b ON e.mgr=b.empno ORDER BY b.ename;
外连接:可以查询出即使列中包含NULL值的数据也可以查询出来
外部连接运算符 (+) 。在使用(+)的字段,可能包含NULL值
例如:查询出部门的员工的情况(列出所有部门)
SELECT e.ename, d.dname FROM emp e ,dept d
WHERE d.deptno = e.deptno(+) ORDER BY d.dname;
SELECT...
FROMtable1, table2
...
WHEREtable1.column1 = table2.column2 (+);
WHEREtable1.column1 (+) = table2.column2;
SELECTe.ename, d.dname FROM emp e ,dept d
WHEREd.deptno = e.deptno(+) ORDER BY d.dname;
SELECTe.ename, d.dname FROM emp e ,dept d
WHEREd.deptno(+) =e.deptno ORDER BY d.dname;
只能一侧使用外连接运算符(+),否则将提示错误SQL提供嵌套子查询机制,即在一个查询中嵌套另一个 select - from - where查询语句.子查询中嵌套子查询,最多可以嵌套255层
例如:查询工资高于SMITH工资的所有员工
select * from emp where sal>(select sal from emp where ename='SMITH')
可以使用all关键词
例如:查询工资高于所有部门的平均工资的员工
select * from emp where sal>all(select avg(sal) from emp group by deptno)
--查询工资高于任何部门的平均工资的员工
■ UPDATE和DELETE使用子查询
WHERE employee_id = 4;
DELETEFROM emp
WHEREsal >
(SELECT AVG(hisal)
FROM salgrade);
ROWNUM可以返回结果集的行号,查询返回的第一行编号为1,第二行编号为2,依此类推
例如,查询EMP表的相关信息
SELECT ROWNUM, empno, ename, deptno FROM EMP;
可以将ROWNUM使用在WHERE子句中
SELECT ROWNUM, empno, ename, deptno
FROM EMP where empno=7369;
ROWNUM行号并不是永久固定的,是每次动态重新生成的。此时如果想查找第6-10条记录,用between…and…的方式是没有数据的。这个时候要想真正的实现这种查询思路:先查询前10条记录,之后再显示5条记录,要依靠子查询完成。
SELECT * FROM (
SELECT ROWNUM M,EMPNO,ENAME,JOB,HIREDATE,SAL FROM EMP
WHERE ROWNUM<=10
) TEMP WHERE TEMP.M>5;
或写成
SELECT * FROM (
SELECT ROWNUM M,EMPNO,ENAME,JOB,HIREDATE,SAL FROM EMP
) WHERE M>5 AND M<=10;
按照这种方式,只需要替换掉最大最小值就可以实现分页的思想
■ 数据库对象
序列Sequence■ 创建序列
CREATE SEQUENCE sequence_name
[START WITH start_num]
[INCREMENT BY increment_num]
[ { MAXVALUE maximum_num |NOMAXVALUE } ]
[ { MINVALUE minimum_num |NOMINVALUE } ]
[ { CYCLE | NOCYCLE } ]
[ { CACHE cache_num |NOCACHE } ]
[ { ORDER | NOORDER } ];
SELECT* FROM user_sequences
ORDERBY sequence_name;
删除序列
删除序列使用DROP SEQUENCE语句
例如,删除s_test3序列
DROP SEQUENCE s_test3;
■ 索引
索引是与表关联的可选结构。可以创建索引以加快对表执行SQL语句的速度。就像书的索引可以帮助我们更快速的查找信息一样,Oracle中的索引也提供了一种更快地访问表数据的途径。
应该建索引列的特点:
1)在经常需要搜索的列上,可以加快搜索的速度;
2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
不应该建索引列的特点:
第一,对于那些在查询中很少使用或者参考的列不应该创建索引。
第二,对于那些只有很少数据值的列也不应该增加索引。
第三,对于那些定义为blob数据类型的列不应该增加索引。
索引的特点
优点:
第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
B树索引在Oracle中是一个通用索引。
在创建索引时它就是默认的索引类型。
B树索引可以是一个列的(简单)索引,也可以是组合/复合(多个列)的索引。B树索引最多可以包括32列。
B-tree 特点: 适合与大量的增、删、改(OLTP) 不能用包含OR操作符的查询; 适合高基数的列(唯一值多) 典型的树状结构; 每个结点都是数据块; 大多都是物理上一层、两层或三层不定,逻辑上三层; 叶子块数据是排序的,从左向右递增; 在分支块和根块中放的是索引的范围;
查看索引
■ 位图索引
在以下情况,通常不值得创建索引:
表比较小
在查询中不经常使用列作为条件
预计多数查询检索的行要超过表中总数行数的一定比例,如百分之十
表更新比较频繁
被索引的列将作为表达式的一部分进行引用
默认的索引类型,平衡树索引,适用于高基数(不同值的程度高)的列。除非有特殊原因需要使用不同的索引类型或功能,否则用正常的B树索引即可.
B树索引的一种形式,用于强制执行列值的唯一性.经常与主键和唯一键约束一起使用,但也可以独立于约束而创建
对于包含低基数列以及在SQL语句的WHERE子句中使用许多AND或OR运算符的数据仓库环境,非常适合使用这种索引。
适用于应用了SQL函数的列。可与B树索引类型或位图索引类型结合使用
--创建视图
create view v1 as select * from p3;
--查询视图
select * from v1;
--创建视图
create view v2 as
select p.name as pname,c.name as cname from
person p inner join car c on p.id=c.pid;
--查询
select * from v2;
)
数据准备
产品类型表
CREATE TABLE product_types (
product_type_id INTEGER CONSTRAINT product_types_pk PRIMARY KEY,
name VARCHAR2(10) NOT NULL
);
产品信息表
CREATE TABLE products (
product_id INTEGER CONSTRAINT products_pk PRIMARY KEY,
product_type_id INTEGER
CONSTRAINT products_fk_product_types
REFERENCES product_types(product_type_id),
name VARCHAR2(30) NOT NULL,
description VARCHAR2(50),
price NUMBER(5, 2)
);
可以使用CREATE VIEW语句创建视图,语法如下
CREATE [OR REPLACE] [{FORCE | NOFORCE}] VIEW view_name
[(alias_name[, alias_name ...])] AS subquery
[WITH {CHECK OPTION | READ ONLY} CONSTRAINT constraint_name];
说明
OR REPLACE:表示替换已存在的同名视图
FORCE:强制创建视图,即使基表不存在也创建
NOFORCE:基表如果不存在,则不创建视图。默认值
view_name:视图名称
alias_name:子查询表达式的别名
subquery:检索基表数据的子查询
WITH CHECK OPTION:表示只有被查询搜索到的数据行才可以进行插入、更新、删除操作。默认是不使用该项
constraint_name:是WITH CHECK OPTION或 WITH READ ONLY选项的约束名
WITH READ ONLY:只能读取基表的数据行
分类
简单视图
查询语句只涉及到一张基表
复杂视图
一般查询涉及到一张或多张表
使用GROUP BY子句或DISTINCT关键字
包含函数的使用
要创建视图,必须给用户授予创建视图CREATE VIEW的权利。可以使用SYS给用户scott授予该权利。
授权语句如下
GRANT CREATE VIEW TO scott;
创建简单视图
使用scott用户创建名为emp_dept_view视图,用以查找部门编号低于20的员工
CREATE VIEW emp_dept_view AS
SELECT *
FROM dept
WHERE deptno < 20
创建名为emp_view的视图,用以查找emp表中除salary列的信息
CREATE VIEW emp_view AS
SELECT empno,mgr, ename,job
FROM emp;
查询emp_dept_view视图的数据
SELECT deptno, dname, loc
FROM emp_dept_view;
查询employees_view视图的数据
SELECT *
FROM emp_view;
使用视图插入数据
可以使用DML语句对cheap_products_view视图进行操作(注意只可用于简单视图)
例如,对视图进行插入操作
INSERT INTO emp_dept_view (deptno, dname, loc)
VALUES (50, 1, ‘West Union', ‘New York’);
查询视图
SELECT deptno, dname, loc
FROM emp_dept_view
WHERE deptno = 50;
创建视图使用CHECK OPTION
如果想DML语句在视图上进行安全的操作,那么可以在查询上设置CHECK OPTION。例如,
CREATE VIEW emp_dept_view2 AS
SELECT *
FROM dept
WHERE deptno < 20
WITH CHECK OPTION CONSTRAINT emp_dept_view2_price;
说明
WHERE子句的限定跟emp_dept_view视图一样,只不过加了CHECK OPTION限制。
(
-widthcheck option
desc t2;
createor replace view v3
as select * from t2 where age<10
with check option;
select* from v3;
--因为设置了with check option所以age>=10时将不能写入
insertinto v3 values(33,22);
通过视图插入一条记录
INSERT INTO emp_dept_view2 (
deptno, dname, loc)
VALUES (25, 'Southern Front', ‘New York’)
说明
由于部门编号是25,通过视图是无法将该记录查出的,视图里面筛选的编号是小于20的,所以插入数据时数据库返回一个错误。
使用READ ONLY创建视图
创建视图的时候使用READ ONLY,那么该将为只读视图
例如,创建emp_dept_view3视图使用READ ONLY
CREATE VIEW emp_dept_view3 AS
SELECT *
FROM dept
WHERE deptno < 15
WITH READ ONLY CONSTRAINT emp_dept_view3_read_only;
插入测试
INSERT INTO emp_dept_view3
(deptno, dname, loc)
VALUES (16, ‘Northern Front’,’New York’);
查看视图定义
可以使用DESCRIBE命令查看视图定义
例如,查看emp_dept_view3视图定义
DESCRIBE emp_dept_view3
同样,可以通过user_views视图查看视图定义信息
例如
SELECT view_name,text_length,text
FROM user_views;
说明,视图的相关列
view_name:视图名
text_length:创建视图的字符长度
text:创建视图的文本代码
read_only:是否为只读视图
创建复杂视图
创建名为products_and_types_view的视图,使用完全外连接
CREATE VIEW emp_and_dept_view AS
SELECT e.empno, e. ename, pt.dname
FROM emp e FULL OUTER JOIN dept pt
USING (deptno)
ORDER BY deptno;
查询视图
SELECT * FROM emp_and_dept_view;
创建视图emp_salary_grades_view,使用内连接
CREATE VIEW emp_salary_grades_view AS
SELECT e.ename, e.job, e.sal, sg.grade
FROM emp e INNER JOIN salgrade sg
ON e.sal BETWEEN sg.losal AND sg.hisal
ORDER BY sg.grade;
查询视图
SELECT * FROM emp_salary_grades_view;
创建视图sal_average_view,使用WHERE子句、GROUP BY、HAVING
CREATE VIEW sal_average_view AS
SELECT ename, AVG(sal) average_price
FROM emp
WHERE sal <3000
GROUP BY empno
HAVING AVG(sal) > 2000
ORDER BY empno;
查询视图
SELECT * FROM sal_average_view;
修改视图
可以使用CREATE OR REPLACE VIEW修改或替换视图
替换sal_average_view视图
CREATE OR REPLACE sal_average_view AS
SELECT empno,AVG(sal) average_price
FROM emp
WHERE sal < 3000
GROUP BY empno
HAVING AVG(sal) > 2000
ORDER BY empno;
可以使用ALTER VIEW去除视图相关约束
例如,去除emp_dept_view2_sal视图的约束
ALTER VIEW emp_dept_view2
DROP CONSTRAINT cheap_products_view2_sal;
可以使用DROP VIEW语句删除视图
例如,删除视图emp_dept_view2
DROP emp_dept_view2
创建和删除同义词
使用同义词访问相同的对象:
方便访问其它用户的对象
缩短对象名字的长度
CREATE [PUBLIC] SYNONYM synonym
FOR object;
同义词
为视图DEPT_SUM_VU 创建同义词
CREATE SYNONYM d_sum
FOR dept_sum_vu;
删除同义词
说明:创建同义词必须要拥有 create synonym | create public synonym的权限。
类似别名,多用于分布式的数据库中。