Oracle数据库基础二:DQL
来源:互联网 发布:淘宝发货后立即回款 编辑:程序博客网 时间:2024/05/16 11:42
数据查询语言(DQL):Data Query Language
- 列别名
- 当SELECT子句中一个字段是函数或者表达式,那么在结果集中该字段的名字就是这个函数或表达式,可读性差,为此可以为列提供一个别名,这样在结果集中会使用该别名作为该字段的名字。应当养成一个好习惯,即:凡是表达式或函数都指定一个别名。
- 别名本身不区分大小写,若希望别名区分大小写或者别名中包含空格,那么需 要使用双引号将其括起来。
SELECT ename,sal+NVL(comm,0) "sal"FROM emp
查询条件
- OR,AND用于连接多个条件使用
OR的优先级低于AND,所以若希望提高OR的优先级,可以使用括号。- 查看工资高于1000,并且职位是CLERK或者SALESMAN的员工?
SELECT ename,job,sal FROM emp WHERE sal>1000AND (job='SALESMAN'OR job='CLERK')
- LIKE用于模糊匹配字符串
支持两个通配符:
%:0-多个字符(任意个字符)
_:单一的一个字符- 查看名字第二个字母是A的员工?
SELECT ename,sal,deptno FROM emp WHERE ename LIKE '_A%'
- IN(list) 和 NOT IN(listr)
判断在列表中和不在列表中。IN,NOT IN常被用在子查询上使用。- 查看职位是CLERK和SALESMAN的员工?
SELECT ename,job,sal FROM emp WHERE job IN('CLERK','SALESMAN')
- BETWEEN…AND…
判断在一个区间范围内- 查看工资在1500到3000之间的员工?
SELECT ename,sal FROM emp WHERE sal BETWEEN 1500 AND 3000
- 查看工资在1000-3000之间,20和30号部门名字中含有A的员工?
SELECT ename,sal,deptno,job FROM emp WHERE sal BETWEEN 1000 AND 3000 AND deptno IN (20,30) AND ename LIKE '%A%'
- ANY(list),ALL(list)
ANY,ALL是配合>,>=,<,<=使用的
ANY(list):大于列表之一,大于最小
ALL(list):大于列表所有,大于最大
ANY(list):小于列表之一,小于最大
ALL(list):小于列表所有,小于最小
ANY,ALL的列表中不会给定固定值,没有实际意义,它们通常配合子查询使用。
SELECT empno, ename, job, sal, deptno FROM empWHERE sal>ANY(3500,4000,4500)
DISTINCT关键字
DISTINCT可以将结果集中指定字段值一样的记录去重。
查看公司有哪些职位?
SELECT DISTINCT job FROM emp可以按照多字段去重,那么这些字段值的组合没有重复记录出现在结果集中。
SELECT DISTINCT deptno,job FROM emp
ORDER BY子句
ORDER BY用于对查询的结果集按照指定字段的值进行排序。
排序分为:升序(ASC),降序(DESC).默认为升序
ORDER BY子句必须定义在SELECT语句中的最后一个子句上。- 查看公司中工资的排名?
SELECT ename,sal,job FROM emp ORDER BY sal DESC - 查看20号部门的工资排名?
SELECT ename,sal,deptno FROM emp WHERE deptno=20 ORDER BY sal DESC
多字段排序时,ORDER BY是有排序的优先级的,首先按照第一个字段先进行排序,当该字段中有记录值重复时,再将这些记录按照第二个字段排序。依此类推。 - SELECT ename,deptno,sal FROM emp ORDER BY deptno DESC,sal DESC
- 若排序的字段中含有NULL值,NULL被认定为最大值。
- 查看公司中工资的排名?
聚合函数
聚合函数又称为分组函数,多行函数。聚合函数的作用是对结果集指定字段
的值进行统计工作的。MAX(),MIN(),SUM(),AVG()求最大值,最小值,总和,平均值,还有一个是对记录数的统计COUNT()- 查看公司的最高工资是多少?
SELECT MAX(sal) FROM emp
SELECT MAX(sal),MIN(sal), SUM(sal),AVG(sal) FROM emp - 查看公司共多少人?
SELECT COUNT(ename) FROM emp
SELECT COUNT(*) FROM emp
SELECT COUNT(1) FROM emp - 聚合函数忽略NULL值。
SELECT SUM(comm),AVG(comm)FROM emp
SELECT AVG(NVL(comm,0)) FROM emp
- 查看公司的最高工资是多少?
分组GROUP BY
GROUP BY子句可以将结果集按照给定的字段值一样的记录进行分组。配合聚合函数使用可以完成分组统计工作。查看每个部门的平均工资?
SELECT AVG(sal),deptno FROM emp GROUP BY deptno当SELECT中含有聚合函数时,那么凡不在聚合函数中的单独字段,都需要出现在GROUP BY子句中。
查看每种职位的最高工资与最低工资是多少?
SELECT MAX(sal),MIN(sal),job FROM emp GROUP BY jobGROUP BY按照多字段分组时,是将这些字段值组合一样的记录看做一组。
统计同部门同职位的员工的各多少人?
SELECT COUNT(*),deptno,job FROM emp GROUP BY deptno,job查看部门的平均工资,前提是该部门的平均工资高于2000
SELECT AVG(sal),deptno FROM emp WHERE AVG(sal)>2000
GROUP BY deptno
上面的SQL语句会抛出异常,WHERE子句中是不能使用聚合函数做为过滤条件的,原因在于过滤的时机不对。WHERE是伴随查询表中数据逐行进行过滤使用
的,用来确定结果集中可以查询出的条目数。而聚合函数是建立在查询出来的数据基础上进行统计才能得到结果,所以使用聚合函数过滤应当是在WHERE之后进行的。
HAVING子句
HAVING子句可以根据聚合函数进行过滤,并且是用来根据条件过滤 GROUP BY的分组。HAVING不能单独出现,不定义GROUP BY子句不能单独出现HAVING子句。查看部门的平均工资,前提是该部门的平均工资高于2000
SELECT AVG(sal),deptno FROM emp GROUP BY deptno
HAVING AVG(sal)>2000查看平均工资高于2000的那些部门的最高工资是多少?
SELECT MAX(sal),deptno FROM emp GROUP BY deptno
HAVING AVG(sal)>2000
关联查询
关联查询的结果集中的字段来自多张表。这就需要在查询的时候联合多张表进行查询,根据给定的连接条件将表与表的数据建立对应关系,再分别从这些记录中提取要查询的字段来形成结果集中的每条记录。
- 查看每个员工的名字以及其所在部门的名字?
SELECT ename,dname FROM emp,dept WHERE emp.deptno=dept.deptno
- 当在关联查询中要查询的字段在这些表中都出现时,需要使用表名来明确字段所属表。可以为表名取一个别名来简化复杂度。
SELECT e.ename,e.deptno,d.dname FROM emp e,dept d WHERE e.deptno=d.deptno
- 在进行关联查询时若有过滤要求,那么过滤条件必须与连接条件同时成立。
- 查看在NEW YORK工作的员工都有谁?
SELECT e.ename,e.deptno,d.dname,d.loc FROM emp e,dept dWHERE e.deptno=d.deptno AND d.loc='NEW YORK'
关联查询中不指定连接条件或者连接条件无效时,会产生笛卡尔积,
这通常是一个无意义的结果集。
SELECT e.ename,d.dname FROM emp e, dept d
2表一个连接条件,N表查询至少要有N-1个连接条件。
内连接
内连接也是用来完成关联查询的。采用JOIN…ON…的形式关联多表。
- 查看每个员工的名字以及其所在部门名称?
普通关联写法:SELECT e.ename,d.dname FROM emp e,dept d WHERE e.deptno=d.deptno内连接写法:SELECT e.ename,d.dname FROM emp e JOIN dept d ON e.deptno = d.deptno不满足关联条件的记录不会被查询出来。
外链接
外链接在关联查询中除了可以将满足连接条件的记录查询出来之外,还可以将不满足连接条件的记录也列出来。
外链接分为:
左外连接,右外连接,全外连接
左外连接:以JOIN左侧表做为驱动表,该表记录都要查询出来,当某条记录不满足连接条件时,那么在结果集中该条记录来自JOIN右侧表的字段的值全部为NULL。
2种写法:SELECT e.ename,e.job,e.sal, d.dname,d.loc FROM emp e LEFT|RIGHT|FULL OUTER JOIN dept d ON e.deptno=d.deptnoSELECT e.ename,d.dname FROM emp e,dept d WHERE e.deptno(+)=d.deptno
自连接
自连接指的是当前表的一条数据可以对应当前表自己的多条数据。自连接是为了解决数据的属性相同,但是本身又存在上下级关系的树状结构数据。
- 查看每个员工以及其领导的名字?
SELECT e.ename,m.ename FROM emp e,emp m WHERE e.mgr=m.empno(+)SELECT e.ename,m.ename FROM emp e LEFT OUTER JOIN emp m ON e.mgr=m.empno
视图VIEW
视图是数据库对象之一,在SQL语句中体现的角色与表一致。但是视图并非一张 真实存在的表,它只是一个查询语句对应的结果集。
CREATE VIEW v_emp_10ASSELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10DESC v_emp_10
视图对应的子查询中的字段可以指定别名,这样该视图对应的字段名就是这个别名。当一个字段是函数或者表达式,那么该字段必须指定别名
CREATE OR REPLACE VIEW v_emp_10ASSELECT empno id,ename name, sal salary,deptnoFROM empWHERE deptno=10
视图分类
视图根据对应的子查询不同,分为简单视图和复杂视图
简单视图:对应的子查询不含有函数,表达式,分组,去重,关联查询。
除了简单视图就是复杂视图简单视图可以进行DML操作,对该视图的操作就是对该视图数据来源的基础表进行的操作。
复杂视图不允许进行DML操作。对简单视图进行DML操作也不能违反基础表的
约束条件。对视图进行DML操作,视图对基础表操作时,只能对视图可见的字段进行。INSERT INTO v_emp_10 (id,name,salary,deptno) VALUES (1001,’JACK’,3000,10)
UPDATE v_emp_10 SET salary=4000 WHERE id=1001
DELETE FROM v_emp_10 WHERE id=1001
对视图的不当DML操作会污染基表数据即:对视图进行DML操作后,视图对基础表对应数据进行该DML操作,但是操作后视图却对该记录不可见。
INSERT INTO v_emp_10 (id,name,salary,deptno) VALUES (1001,'JACK',3000,20)UPDATE v_emp_10 SET deptno=20DELETE不会产生污染现象。DELETE FROM v_emp_10 WHERE deptno=20
- 为视图添加检查选项,可以避免对视图操作而导致的对基表的数据污染。
WITH CHECK OPTION
该选项要求对视图进行DML操作后,该记录必须对视图可见。
CREATE OR REPLACE VIEW v_emp_10ASSELECT empno id,ename name, sal salary,deptnoFROM empWHERE deptno=10WITH CHECK OPTION
- 只读选项
WITH READ ONLY
只读选项要求对视图仅能进行查询操作不能进行任何DML操作。
CREATE OR REPLACE VIEW v_emp_10ASSELECT empno id,ename name, sal salary,deptnoFROM empWHERE deptno=10WITH READ ONLY
常用的数据库的数据字典
- USER_OBJECTS:记录用户创建过的所有数据库对象
SELECT object_name,object_type FROM user_objectsWHERE object_type='VIEW' AND object_name LIKE '%FANCQ'
- USER_VIEWS:专门记录曾经创建过的视图信息
SELECT view_name,text FROM user_views
- USER_TABLES:专门记录曾经创建过的表的信息
SELECT table_name FROM user_tables
删除视图
DROP VIEW v_emp_10
创建复杂视图
创建一张视图,包含员工工资及相关部门信息
包含:每个部门的平均工资,最大,最小,工资总和,
以及对应的部门名称,部门编号。
CREATE OR REPLACE VIEW v_emp_salinfoASSELECT AVG(e.sal) avg_sal, MAX(e.sal) max_sal, MIN(e.sal) min_sal, SUM(e.sal) sum_sal, d.deptno,d.dname,d.locFROM emp e,dept dWHERE e.deptno=d.deptnoGROUP BY d.deptno,d.dname,d.loc
- 查看哪些员工的工资高于其所在部门平均工资?
SELECT e.ename,e.sal,e.deptno FROM emp e,v_emp_salinfo vWHERE e.deptno=v.deptno AND e.sal>v.avg_sal
序列SEQUENCE
序列是数据库对象之一,作用是根据指定的规则生成一系列数字。通常使用序列生成的数字是为表中的主键字段提供值使用。
CREATE SEQUENCE seq_emp_idSTART WITH 1INCREMENT BY 1
序列支持两个伪列:
NEXTVAL:获取序列的下一个数字,如果是新创建的序列,那么会从START WITH开始返回。之后则是用上次生成的数字加上步长来得到本次生成的数字返回。需要注意,序列是不能后退的。并且不受事务控制。
CURRVAL:获取序列最后生成的数字,新创建的序列至少调用NEXTVAL生成一个数字后才可以使用。CURRVAL不会导致序列步进。
SELECT seq_emp_id.NEXTVAL FROM dualSELECT seq_emp_id.CURRVAL FROM dual
- 使用序列为EMP表主键字段提供值
INSERT INTO emp(empno,ename,job,sal,deptno)VALUES(seq_emp_id.NEXTVAL,'JACK','CLERK',3000,10)SELECT * FROM emp
删除一个序列
DROP SEQUENCE seq_emp_id序列的数据字典
SELECT * FROM USER_SEQUENCES
索引INDEX
索引是数据库对象之一,作用是提高查询效率索引的创建时是数据库自行完成的,并且数据库会在适当的时候自动使用索引。
CREATE INDEX idx_emp_ename ON emp(ename)
索引适用范围
- 经常出现在WHERE中和ORDER BY中的字段要添加索引。
- 经常出现在DISTINCT后面的字段也可以添加索引。
- 需要注意,对于字符串类型字段,若在WHERE中使用LIKE进行过滤时,是不会用到索引的。
PLSQL
PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算。PL/SQL 只有 Oracle 数据库有。 MySQL 目前不支持 PL/SQL
变量声明:
declare myapple number(10);标识符
- 变量必须以字母开头,其后可以跟字母,数字 _ $和#
- 变量长度最多30个字符
- 变量名中不能有空格
变量类型
目前oracle中varchar和varchar2没区别
除了Number,varchar2,char,date等常用外
还有boolean 和对象类型- 数据类型转换
To_char():number,date转varchar2
To_date:将char转date
To_number:将char转number
自动类型转换:number->char
基本程序结构和语句
IF
- IF THEN 结构
IF condition THEN S; END IF;
- IF THEN ELSE
IF condition THEN S1; ELSE S2;END IF;
- IF THEN ELSIF ELSE
IF(boolean_expression 1)THEN S1; -- Executes when the boolean expression 1 is true ELSIF( boolean_expression 2) THEN S2; -- Executes when the boolean expression 2 is true ELSIF( boolean_expression 3) THEN S3; -- Executes when the boolean expression 3 is true ELSE S4; -- executes when the none of the above condition is true END IF;
实例
IF THEN 结构实例
DECLARE a number(2) := 10;BEGIN a:= 10; -- check the boolean condition using if statement IF( a < 20 ) THEN -- if condition is true then print the following dbms_output.put_line('a is less than 20 ' ); END IF; dbms_output.put_line('value of a is : ' || a);END;
IF THEN ELSIF ELSE 结构实例
DECLARE a number(3) := 100;BEGIN -- check the boolean condition using if statement IF( a < 20 ) THEN -- if condition is true then print the following dbms_output.put_line('a is less than 20 ' ); ELSE dbms_output.put_line('a is not less than 20 ' ); END IF; dbms_output.put_line('value of a is : ' || a);END;
IF THEN ELSE 结构实例
DECLARE a number(3) := 100;BEGIN -- check the boolean condition using if statement IF( a < 20 ) THEN -- if condition is true then print the following dbms_output.put_line('a is less than 20 ' ); ELSE dbms_output.put_line('a is not less than 20 ' ); END IF; dbms_output.put_line('value of a is : ' || a);END;
循环结构
- LOOP
LOOP Sequence of statements;END LOOP;
实例
DECLARE x number := 10;BEGIN LOOP dbms_output.put_line(x); x := x + 10; IF x > 50 THEN exit; END IF; END LOOP; -- after exit, control resumes here dbms_output.put_line('After Exit x is: ' || x);END;
- FOR
FOR counter IN initial_value .. final_value LOOP sequence_of_statements;END LOOP;
实例
DECLARE a number(2);BEGIN FOR a in 10 .. 20 LOOP dbms_output.put_line('value of a: ' || a); END LOOP;END;
- WHILE
语法
WHILE condition LOOP sequence_of_statementsEND LOOP;
实例
DECLARE a number(2) := 10;BEGIN WHILE a < 20 LOOP dbms_output.put_line('value of a: ' || a); a := a + 1; END LOOP;END;
条件结构
- CASE
CASE selector WHEN 'value1' THEN S1; WHEN 'value2' THEN S2; WHEN 'value3' THEN S3; ... ELSE Sn; -- default case END CASE;
实例
DECLARE grade char(1) := 'A';BEGIN CASE grade when 'A' then dbms_output.put_line('Excellent'); when 'B' then dbms_output.put_line('Very good'); when 'C' then dbms_output.put_line('Well done'); when 'D' then dbms_output.put_line('You passed'); when 'F' then dbms_output.put_line('Better try again'); else dbms_output.put_line('No such grade'); END CASE;END;
存储过程
第一个存储过程
create or replace procedure proc1(para1 varchar2,para2 out varchar2,para3 in out varchar2) asv_name varchar2(20);begin v_name :='zhangsf'; para3 := v_name;dbms_output.put_line('para3:'||para3);end;
上面就是一个最简单的存储过程。一个存储过程大体分为这么几个部分:
- 创建语句:create or replace procedure 存储过程名
如果没有or replace语句,则仅仅是新建一个存储过程。如果系统存在该存储过程,则会报错。Create or replace procedure 如果系统中没有此存储过程就新建一个,如果系统中有此存储过程则把原来删除掉,重新创建一个存储过程。 - 存储过程名定义:包括存储过程名和参数列表。参数名和参数类型。参数名不能重复, 参数传递方式:IN, OUT, IN OUT
- IN 表示输入参数,按值传递方式。
- OUT 表示输出参数,可以理解为按引用传递方式。可以作为存储过程的输出结果,供外部调用者使用。
- IN OUT 即可作输入参数,也可作输出参数。
参数的数据类型只需要指明类型名即可,不需要指定宽度。
参数的宽度由外部调用者决定。
过程可以有参数,也可以没有参数 - 变量声明块:紧跟着的as (is )关键字,可以理解为pl/sql的declare关键字,用于声明变量。
变量声明块用于声明该存储过程需要用到的变量,它的作用域为该存储过程。另外这里声明的变量必须指定宽度。遵循PL/SQL的变量声明规范。 - 过程语句块:从begin 关键字开始为过程的语句块。存储过程的具体逻辑在这里来实现。
- 异常处理块:关键字为exception ,为处理语句产生的异常。该部分为可选
- 结束块:由end关键字结果。
存储过程的参数传递方式
存储过程的参数传递有三种方式:IN,OUT,IN OUT .
IN 按值传递,并且它不允许在存储过程中被重新赋值。如果存储过程的参数没有指定存参数传递类型,默认为IN
create or replace procedure proc1( para1 varchar2, para2 out varchar2, para3 in out varchar2) as v_name varchar2(20);begin para1 := 'aaa'; para2 := 'bbb'; v_name :='zhangsf'; para3 := v_name dbms_output.put_line('para3:'||para3); null;end;
OUT 参数:作为输出参数,需要注意,当一个参数被指定为OUT类型时,就算在调用存储过程之前对该参数进行了赋值,在存储过程中该参数的值仍然是null.
首先,我们要明白,我们无法在存储过程的定义中指定存储参数的宽度,也就导致了我们无法在存储过程中控制传入变量的宽度。这个宽度是完全由外部传入时决定的。
我们再来看看OUT类型的参数的宽度。
create or replace procedure proc2(para1 varchar2,para2 out varchar2,para3 in out varchar2) asv_name varchar2(2);beginpara2 :='aaaaaaaaaaaaaaaaaaaa';end;
–调用proc2
var p1 varchar2(1);
var p2 varchar2(1);
var p3 varchar2(1);
exec :p2 := ‘a’;
exec proc1(:p1,:p2,:p3);
在该过程中,p_para2被赋予了20个字符a.
而在外部的调用过程中,p2这个参数仅仅被定义为varchar2(1).
而把p2作为参数调用这个过程,却并没有报错。而且它的真实值就是20个a
执行这个过程,仍然正确执行。
可见,对于IN参数,其宽度是由外部决定。
对于OUT 和IN OUT 参数,其宽度是由存储过程内部决定。
因此,在写存储过程时,对参数的宽度进行说明是非常有必要的,最明智的方法就是参数的数据类型使用%type。这样双方就达成了一致。
参数的默认值
存储过程的参数可以设置默认值
create or replace procedure procdefault( p1 varchar2, p2 varchar2 default 'mark') asbegin dbms_output.put_line(p2);end;
mark
可以通过default 关键字为存储过程的参数指定默认值。在对存储过程调用时,就可以省略默认值。
需要注意的是:默认值仅仅支持IN传输类型的参数。OUT 和 IN OUT不能指定默认值
对于有默认值的参数不是排在最后的情况。
create or replace procedure procdefault2( p1 varchar2 default 'remark', p2 varchar2) asbegin dbms_output.put_line(p1);end;
第一个参数有默认值,第二个参数没有。如果我们想使用第一个参数的默认值时
exec procdefault2(‘aa’);
这样是会报错的。
那怎么变呢?可以指定参数的值。
SQL> exec procdefault2(p2 =>’aa’);
remark
这样就OK了,指定aa传给参数p2
存储过程内部块
内部块
我们知道了存储过程的结构,语句块由begin开始,以end结束。这些块是可以嵌套。在语句块中可以嵌套任何以下的块。
Declare .. beign ... exception ... end;create or replace procedure innerBlock( p1 varchar2) as o1 varchar2(10) := 'out1';begin dbms_output.put_line(o1); declare inner1 varchar2(20); begin inner1 := 'inner1'; dbms_output.put_line(inner1); declare inner2 varchar2(20); begin inner2 := 'inner2'; dbms_output.put_line(inner2); end; exception when others then null; end;end;
需要注意变量的作用域。
触发器
传送:
http://www.cnblogs.com/xcnblog3035/p/5236877.html
- Oracle数据库基础二:DQL
- oracle数据库基础二
- oracle数据库的数据查询语言DQl
- Oracle数据库基础(二)
- 数据库基础--SQL 语言(DQL、DDL、DML、DCL)
- oracle数据库 DQL、DML、DDL、DCL的概念与区别
- MySQL/Oracle数据库的基础(二)
- oracle数据库基础学习(二)
- MYSQL基础(DQL)
- 数据库DQL语句
- DQL数据库查询语言
- Oracle系统体系结构概述(二)-oracle数据库基础
- Oracle数据库基础(二)--数据类型,约束,oracle函数
- Oracle SQL基础之(一)语句和函数 DCL DDL DQL
- Oracle学习总结(二)——数据库基础
- 数据库查询操作(DQL)
- 【Oracle数据库】Oracle数据库基础
- DQL
- eclipse4.2.1插件安装(二)之Eclipse HTML Editor
- Webpack 基础
- 简单找规律数学题Euler theorem
- HTTP简单介绍
- Firefox浏览器设置字符编码格式
- Oracle数据库基础二:DQL
- super关键字,this关键字,及其两者区别.final关键字
- 学习笔记TF042:TF.Learn、分布式Estimator、深度学习Estimator
- nyoj 27水池数目
- HDU 6156 Palindrome Function(数位 回文串 17CCPC网络赛)
- 62.寻找路径
- Girls and Boys||HDU1068
- NSThread
- A. Generous Kefa(Round #429 (Div. 2))