oracle 从入门到精通一

oracle产品线围绕企业开发平台的
企业开发平台四大组件:unix,weblogic中间件,java编程语言,oracle数据库

数据库管理:dba
数据库编程:分两部分
    sql编程
    pl/sql编程(子程序,触发器,面向对象,游标)

下载    官方网站下载相应的版本到本地,并解压缩。
环境    在启动安装之前的环境配置。
安装

只要是行与列的集合就是数据表

SQL> ed hello
SQL> @hello

数据库开发都以dml操作为主
数据库设计时以ddl操作为主

数据类型 number(7,2)  小数位是两位,总共是7位,整数是5位

##############################################################################

简单查询的最大特征在于可以控制列,它无法进行数据行的控制。

select [distinct] *| 列名 [别名],列名 [别名],... from 表名 [别名];

distinct是去掉重复的行。指所查询出来的所有列内容都一样的去重。

执行顺序是先from再select

子句有两个 一个是select ...,一个是from ...。或者还会有where ...,order by ...。

进行数据的投影-----控制所需要显示的数据列。

支持四则运算,再加上别名就美观了。

select aa,bb,cc*2 from emp;

select aa,bb,cc*2 nian from emp;

select trans_new_price-2 sum from tis_ft_adjust_price where rownum <=5;

select trans_new_price*2 sum from tis_ft_adjust_price where rownum <=5;

拼接列的值。列名1 || 列名2

select adjust_time || operator_id ww from tis_ft_adjust_price where rownum <=5;

格式化输出,字符串用单引号引起来,数字直接写,不用引用。

select 'tj:'||adjust_reason||',ti:'||ADJUST_TIME ww from tis_ft_adjust_price where rownum <=5;
 

##############################################################################

限定查询,控制数据行

1.sql语句的执行顺序

第三步:选出所需要的数据列  select *

第一步:确定数据来源  from table

第二步:筛选数据行  where 条件

第四步:数据排序  order by

2.限定符号的使用,以下是标准sql支持的。

若干个条件判断符,

>,<,=,>=,<=,!=,

is not null,is null

like,not like  _匹配任意一位字符,匹配多位。

in,not in  not in中不能有null,in可以有。where 字段  in(8899,2234,7554,null); 不连续的行

betwwen...and  where 字段|数值 betwwen  最小值 and 最大值;  连续的行

以上只能使用一次,如果有多个条件,则用逻辑运算符:

and,or,not(非)

书写标准,先写查列,再将select from where 分别写三行,再写各种限定,表限定,行限定,列限定。这是按照执行顺序写的。

desc tis_bk_user;
select user_id
from tis_bk_user
where rownum <=5;

select *
from tis_ft_g_owner_clear
where trans_freight between 10000 and 11000;

betwwen...and...是一个运算符,也可以用关系运算符与逻辑运算符组合来使用,但效率低

如:where trans_freight>10000 and trans_freight<11000

oracle所有的运算符不受数据类型的控制,以上是对数字的判断,字符串意义不大,重点是对日期时间的判断。

select clear_time
from tis_ft_g_owner_clear
where clear_time between '2015-07-28 11:13:57' and '2015-07-29 11:47:07';

select *
from tis_bk_role
where not role_id<to_number('001056'); #  to_number为函数

空判断

select null + 1 from emp;  这个表有几行,就返回几行空行

null不能使用关系运算,关系可以判断的是数据,null属于一个未知的数据。

#in

select *
from tis_bk_role
where role_id  in (001050,001025,001034);

select * from emp where enam like '%%';

select * from emp;

这两条是一样的结果,下面虽然效率高,但上面在程序开发中方便后续扩充

order by 字段1 asc|desc,字段2 asc|desc...

默认是按照自然顺序排列的,也就是输入数据时的顺序。也可以进行多字段的排序。如果某一个字段重复的话。

所有的排序操作都是在where之后执行的,order by 永远最后执行

##############################################################################

单行函数

字符串函数  replace(),substr(),length(),

select user_accout,initcap(USER_ACCOUT)
from tis_bk_user;

select user_accout,length(USER_ACCOUT)
from tis_bk_user;

select * 
from tis_bk_user 
where length(user_accout)=5;

replace(列名|数据,‘原内容’,'替换的内容')
利用replace()可以取消字符串中的空格
create table t2 as select * from tis_bk_user_info;
select replace(user_name,'木','森')
from t2
where user_name like '%神木%';

下标从1开始的
substr(列名|数据,开始点)  指定位置到结尾
substr(列名|数据,开始点,长度)  截取范围
select substr('helloworld',3) from dual;
select substr('helloworld',3,5) from dual;
截取后三个
select substr('helloworld',length('helloworld')-2) from dual;
select substr('helloworld',-3)

数值函数

mod(),round(),trunc()

round()    四舍五入
-2小数点前两位,2小数点后两位
select
  round(998.8876568),
  round(9999.77777655,2),
  round(9999.77777655,-2),
  round(-15.132)
from dual;

trunc()    不四舍五入进行处理

mod()    求模(求余数)

日期函数

/*日期函数(oracle自己特色)

如何可以取得当前的日期,用伪列sysdata

伪列sysdate,systimestamp,
虚拟表dual*/
select sysdate,systimestamp from dual;

/*日期计算模式
日期+1    后一天
日期-1    前一天
日期-日期    
没有日期+日期*/

select sysdate,sysdate-2,sysdate+3 from dual;

/*如果只是依靠天娄无法获得一个准确的年或月,所以oracle里面才提供了日期处理函数,
利用这些函数可以避免闰年与闰月的问题*/

/*计算下一个周二的日期*/
select next_day(sysdate,'TUE') from dual;

trunc(months_betwwen(sysdate,hiredate)/12) year
trunc(mod(months_between(sysdate,hiredate)/12)) month

转化函数

利用to_char进行年,月,日的拆分,只是提供一个思路,oracle本身的一个自动转换。
to_char
下面两个几乎等于无用
to_date
to_number

to_char(列|日期|数字,格式)
select to_char(sysdate,'yyyy:mm:dd'),to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

select to_char(98468472392823,'L999,999,999,999,999,999') from dual;

通用函数

nvl()
decode()

##############################################################################

多表查询(进入了复杂查询的阶段)

笛卡尔积一直存在,无法消除,虽然能消除显示问题。数据量一大,多表查询会带来严重的问题。

多表查询之中的多张表一定要有关联关系,否则不能查询

判断程序慢的两种方法:程序算法慢(cpu 占用率高),数据库数据大(内存占用高)

由数据量决定,用不用多表查询,如果数据量几百行,随便用,几十万行,就得选用其它技术点了。

select count(*) 
from costs a,prod b
where a.prod_id=b.prod.id;

有明确的关联字段的案例如下:

确定要使用的数据表  emp,dept

确定已知的关联字段  prod_id

select a.pname,a.sal,b.loc,b.job

from emp a,dept b

where a.prod_id=b.prod_id;

没有明确的关联字段,而是关联条件

select e.name,e.sal,s.grade

from emp e,salgrade s

where e.sal between s.lowsal and s.higsal;

分析过程如下:(关联字段或关联条件)

第一:写出第一张表的查询

第二:引入第二张表,加表,加字段,加条件,消除笛卡尔积的显示

第三:引入第三张表,加表,加字段,加条件,用and连接。

##############################################################################

表的连接操作

连接操作本身就是一个查询

select * from dept;
select * from salgrade;
两张表的所有行组合,from之中
select * from salgrade,dept;
两张表所有组合的任意列,select list之中
select a.grade,b.dname from salgrade a,dept b;

对于两张表进行多表查询对于消除笛卡尔积主要依靠连接模式来处理的,表的连接模式有两种:

内连接:在之前都利用where子句来消除笛卡尔积,只有满足条件的数据才会显示出来

外连接:不用管是左还是右,只要所需要的数据全部显示就可以了。分左外连接,右外连接,全外连接(几乎不会出现)

where d.deptno=s.deptno(+)  左连接

where d.deptno(+)=s.deptno  右连接

(+)是oracle特有的(oracle9 之前)

left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).
B表记录不足的地方均为NULL.

http://www.cnblogs.com/kerrycode/p/5935704.html

# oracle中||表示连接的意思

select a.user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a,tis_ft_user_info b 
where rownum<5 and a.user_id(+)=b.user_id;

select a.user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a left join tis_ft_user_info b on a.user_id=b.user_id
where rownum<5;

select user_id,a.user_account||','||a.user_type aa,b.user_name
from tis_ft_user a inner join tis_ft_user_info b using(user_id)
where rownum<5;

inner join(相等联接或内联接)

SELECT * FROM a
INNER JOIN b
ON a.aID =b.bID

等同于以下SQL句:
SELECT *
FROM a,b
WHERE a.aID = b.bID 

##############################################################################

数据集合操作  并集,交集,差集,补集

如果我们需要将两个select语句的结果作为一个整体显示出来,我们就需要用到union或者union all关键字。union(或称为联合)的作用是将多个结果合并在一起显示出来。

union和union all的区别是,union会自动压缩多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复。
1. union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
2. union All:对两个结果集进行并集操作,包括重复行,不进行排序;
3. intersect:对两个结果集进行交集操作,不包括重复行,同时进行默认规则的排序;
4. minus:对两个结果集进行差操作,不包括重复行,同时进行默认规则的排序。

可以在最后一个结果集中指定Order by子句改变排序方式。

SELECT * FROM emp  
WHERE sal < 1500;
结果:
SMITH	CLERK	7902	17-DEC-80	800		20
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
ADAMS	CLERK	7788	23-MAY-87	1100		20
JAMES	CLERK	7698	03-DEC-81	950		30
MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;
结果:
ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
ADAMS	CLERK	7788	23-MAY-87	1100		20
MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal < 1500
union  
SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;
结果:
SMITH	CLERK	7902	17-DEC-80	800		20
ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
ADAMS	CLERK	7788	23-MAY-87	1100		20
JAMES	CLERK	7698	03-DEC-81	950		30
MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal < 1500
union all
SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;
SMITH	CLERK	7902	17-DEC-80	800		20
ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
ADAMS	CLERK	7788	23-MAY-87	1100		20
ADAMS	CLERK	7788	23-MAY-87	1100		20
JAMES	CLERK	7698	03-DEC-81	950		30
MILLER	CLERK	7782	23-JAN-82	1300		10
MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal < 1500
intersect  
SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;
WARD	SALESMAN	7698	22-FEB-81	1250	500	30
MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
ADAMS	CLERK	7788	23-MAY-87	1100		20
MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal < 1500
minus
SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;
SMITH	CLERK	7902	17-DEC-80	800		20
JAMES	CLERK	7698	03-DEC-81	950		30

##############################################################################

统计函数(也叫分组函数)

count(),sum(),avg(),:支持数字

max(),min():支持数字,字符串,日期数据类型

在没有数据的时候,只有count返回结果,其它是null

count()有三种形式:

count(*):统计所有的数据行

count(字段):统计所有不为空的数据行数

count(distinct 字段)统计所有不重复的数据行

##############################################################################

分组统计

group by  找重复的列

第一步:确定数据来源  from table

第二步:筛选数据行  where 条件

第三步:针对筛选的数据行进行分组  group by 分组字段1,分组字段2,

第四步:选出所需要的数据列  select *|分组列

第五步:数据排序  order by

select sid,count(*),min(statistic#),max(statistic#)
from v$sesstat
group by sid;

统计函数
是针对一张表的完整统计,

分组统计
分组的前提是存在有重复,允许单独一行记录进行分组。


分组的时候有一些约定条件
1、如果查询不使用group by 子句,那么select 子句中只允许出现统计函数,其它任何字段不允许出现。
或者说是统计函数不与其它字段同时出现。

正确
select count(*) from emp;
错误
select empno,count(*) from emp;
2、如果查询中使用group by 子句,那么select 子句中只允许出现分组字段,统计函数,其它任何字段都不允许出现。
正确

select job,count(*) from emp group by job;
错误
select ename,job,count(*) from emp group by job;
3、统计函数允许嵌套,但是嵌套之后的select 子句里面只允许出现嵌套函数,而不允许出现任何字段,包括分组字段。
正确

select max(avg(sal)) from emp group by deptno;
错误
select deptno,max(avg(sal)) from emp group by deptno;
可以将下面的查询结果想象成一张数据表,这张表没有group by子句,那么就回到了第一个约定条件,只允许出现统计函数。
所以就解释了第三个约定条件。
select deptno,avg(sal) from emp group by deptno;

##############################################################################

多表查询与分组统计

having子句,此时就不能用where子句了,having 跟随group by 而出现。

针对分组后的数据进行筛选,是在group by

select job,avg(sal)

from emp

group by job

having avg(sal)>2000;

where 与having的区别

1:where 是在group by 之前执行的,先选出可以参与分组的数据,不能使用统计函数。

2:having是在group by 之后执行的,可以使用统计函数。

##############################################################################

子查询

子查询并没有特殊的语法,可以出现在任意子句之中(select ,from,where,group by,having,order by),但必须用()声明

子查询就是查询的嵌套。

##############################################################################

在where子句中使用子查询
where子句主要是进行数据的筛选,而且通过分析可以发现,
单行单列,单行多列,多行单列,都可以在where子句
中出现。

--查单行单列的
--要求查出谁的工资最低
不能直接拿800这个数据直接使用,因为这个数据是需要统计出来的,
而想要知道这个内容,可以利用min();
--所以分两步
1.先查出最低的
select min(sal) from emp;
2.再用最低的去过滤
以上查询返回单行单列,本质上就是一个数值。
select * from emp
where sal=(select min(sal) from emp);

上下两个查询,下面是写死了,上面动态计算的,比较灵活。
select * from emp
where sal=800;

--查出公司雇佣最早的雇员
select * from emp
where hiredate=(select min(hiredate) from emp);

--子查询返回单行多列(了解就行,用的不多)
--查出与scott工资相同,职位相同的所有雇员
select * from emp
where 
(sal,job)=(select sal,job from emp where ename='SCOTT')
and ename<>'SCOTT';


--子查询返回多行单列(比较重要)
--子查询返回多行单列实际上相当于告诉用户一个数据的操作范围,从...到...
而如果想要进行范围的判断,在where中提供有三个运算符,in,any,all
in与not in

select sal from emp where job='MANAGER';
上面返回了多行单列
select * from emp
where sal in 
(select sal from emp where job='MANAGER');
多行单列就相当于给出了我们一个查询范围

select * from emp
where sal not in 
(select sal from emp where job='MANAGER');

not in中不能有空,否则查不出来。一定要保证子查询中不能有空
select * from emp
where comm not in
(select comm from emp);

any操作

sal=any        功能上与in没有区别
sal>any        比子查询返回内容的最小值要大
sal<any        比子查询返回内容的最大值要小

select * from emp
where sal>any
(select sal from emp where job='MANAGER');

all操作

sal>all        比子查询返回内容的最大值要大
sal<all        比子查询返回内容的最小值要小

select * from emp
where sal<all
(select sal from emp where job='MANAGER');

##################################################################

exists()条件

主要测试在一个子查询中行的存在
如果子查询有数据返回(至少有一行,不管什么数据)就表示条件满足,那么就可以显示出数据,否则不显示

select * from emp
where exists (
select * from emp where deptno=20);

如果子查询有数据返回,外部查询就有数据返回,子没有父就没有

exists()与in()区别
exists()以行为主
in()以列(数据)为主
exists()要比in()性能更高,判断行有无比判断数据有无更快。


使用exists()只关心子查询里面返回的是否有行,至于什么行,不关心
select * from emp
where exists(
select 'hello' from dual where 1=1);

select * from emp
where not exists(
select 'hello' from dual where 1=2);

##################################################################

having子句中使用子查询
要使用having必须结合group by子句,要使用group by必须要有分组

部门平均工资大于公司平均工资的部门编号,人数与部门工资

select deptno,count(*),avg(sal) from emp
group by deptno
having avg(sal)>(select avg(sal) from emp);


select子句中使用子查询(基本没用)
意义不大,性能不高

肯定使用多表查询
select e.empno,e.job,e.ename,d.dname
from emp e,dept d
where e.deptno=d.deptno;

变换成子查询
select e.empno,e.job,e.ename,
    (select dname d from dept d where d.deptno=e.deptno)
from emp e;

实际上在select子句里面出现的子查询核心目的在于:行列转换

from子句中出现子查询(重点)

主要是思路问题,是需要去思考的

猜你喜欢

转载自blog.csdn.net/ccbulougen/article/details/82114435