天天看點

oracle資料庫從入門到精通

oracle産品線圍繞企業開發平台的

企業開發平台四大元件:unix,weblogic中間件,java程式設計語言,oracle資料庫

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

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

from tis_bk_role

where not role_id<to_number('001056');

空判斷

select null + 1 from emp;  這個表有幾行,就傳回幾行空行

null不能使用關系運算,關系可以判斷的是資料,null屬于一個未知的資料。

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裡面才提供了日期處理函數,利用這些函數可以避免閏年與閏月的問題

計算下一個周二的日期
SQL> 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特有的

left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為準的.

換句話說,左表(A)的記錄将會全部表示出來,而右表(B)隻會顯示符合搜尋條件的記錄(例子中為: A.aID = B.bID).

B表記錄不足的地方均為NULL.

三種寫法

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

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;

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)

仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充.

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

sql語句如下:

SELECT * FROM a

INNER JOIN b

ON a.aID =b.bID

等同于以下SQL句:

SELECT *

FROM a,b

WHERE a.aID = b.bID

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

資料集合操作  并集,交集,差集,補集

是将若幹個查詢結果合并在一起,若幹個資料查詢結果所傳回的資料結構必須一緻。

union  取消重複行

union all

intersect  交集

minus  差集

如果我們需要将兩個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;

7369	SMITH	CLERK	7902	17-DEC-80	800		20
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7900	JAMES	CLERK	7698	03-DEC-81	950		30
7934	MILLER	CLERK	7782	23-JAN-82	1300		10


SELECT * FROM emp  
WHERE sal  BETWEEN 1000 AND 2000  
ORDER BY 1;

7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7934	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;


7369	SMITH	CLERK	7902	17-DEC-80	800		20
7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7900	JAMES	CLERK	7698	03-DEC-81	950		30
7934	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;


7369	SMITH	CLERK	7902	17-DEC-80	800		20
7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300	30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0	30
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7900	JAMES	CLERK	7698	03-DEC-81	950		30
7934	MILLER	CLERK	7782	23-JAN-82	1300		10
7934	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;

7521	WARD	SALESMAN	7698	22-FEB-81	1250	500	30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7876	ADAMS	CLERK	7788	23-MAY-87	1100		20
7934	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;

7369	SMITH	CLERK	7902	17-DEC-80	800		20
7900	JAMES	CLERK	7698	03-DEC-81	950		30      

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

統計函數(也叫分組函數)

count(),sum(),avg(),:支援數字

max(),min():支援數字,字元串,日期資料類型

在沒有資料的時候,隻有count傳回結果,其它是null

count()有三種形式:

count(*):統計所有的資料行

count(字段):統計所有不為空的資料行數

count(distinct 字段)統計所有不重複的資料行

分組統計

group by  找重複的列

第四步:選出所需要的資料列  select *|分組列

第三步:針對篩選的資料行進行分組  group by 分組字段1,分組字段2,

第五步:資料排序  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);

上下兩個查詢,下面是寫死了,上面動态計算的,比較靈活。

where sal=800;

--查出公司雇傭最早的雇員

where hiredate=(select min(hiredate) from emp);

--子查詢傳回單行多列(了解就行,用的不多)

--查出與scott工資相同,職位相同的所有雇員

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';

上面傳回了多行單列

where sal in

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

多行單列就相當于給出了我們一個查詢範圍

where sal not in

not in中不能有空,否則查不出來。一定要保證子查詢中不能有空

where comm not in

(select comm from emp);

any操作

sal=any        功能上與in沒有差別

sal>any        比子查詢傳回内容的最小值要大

sal<any        比子查詢傳回内容的最大值要小

where sal>any

all操作

sal>all        比子查詢傳回内容的最大值要大

sal<all        比子查詢傳回内容的最小值要小

where sal<all

exists()條件

主要測試在一個子查詢中行的存在

如果子查詢有資料傳回(至少有一行,不管什麼資料)就表示條件滿足,那麼就可以顯示出資料,否則不顯示

where exists (

select * from emp where deptno=20);

如果子查詢有資料傳回,外部查詢就有資料傳回,子沒有父就沒有

exists()與in()差別

exists()以行為主

in()以列(資料)為主

exists()要比in()性能更高,判斷行有無比判斷資料有無更快。

使用exists()隻關心子查詢裡面傳回的是否有行,至于什麼行,不關心

where exists(

select 'hello' from dual where 1=1);

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子句中出現子查詢(重點)

主要是思路問題,是需要去思考的

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

DML包括查詢與更新。

資料的更新包括:增加,修改,删除

更新離不開查詢

資料的增加

資料的修改

資料的删除

先複制一份原始資料

create table myemp as select * from emp;

insert into myemp() values();

常用的三種類型

    字元串:‘字元串’

    數值:直接編寫

    日期:有三種

        sysdate

        根據日期的儲存結構編寫字元串:‘天-年-月’

        利用to_date()将字元串轉換為date型資料

完整文法

值與字段對應即可。

insert into myemp(empno,job,sal,hiredate,ename,deptno,mgr,comm)

values(6666,'清潔工',2000,to_date('1988-09-08','yyyy-mm-dd'),'王二',40,7396,null);

執行上面的語句報下面的錯

ORA-01756: quoted string not properly terminated

将清潔工與王二換成英文即可。或者撤銷NLS_LANG環境變量,再insert就可以了,因為我的系統上有這個變量

但是行插進去了,卻亂碼了(變成???)

[oracle@db Downloads]$ echo $NLS_LANG

AMERICAN_AMERICA.ZHS16GBK

[oracle@db Downloads]$ echo $LANG

en_US.UTF-8

亂碼問題先不處理了,是以先選用英文。

values(6668,'aa',2000,to_date('1988-09-08','yyyy-mm-dd'),'aa1',40,7396,null);

values(6669,'aa',2000,to_date('1986-09-08','yyyy-mm-dd'),'aa2',40,7397,null);

省略字段文法

必須注意要與表中的字段順序一緻。

在開發時盡量使用完整文法,一條資料一行

update 表名 set 字段=内容,字段=内容,...[where 更新條件(s)]

普通的

update myemp set sal=2500,comm=40 where ename='aa2';

帶子查詢的

update myemp set sal=(select avg(sal) from myemp)

where sal=(select min(sal) from myemp);

update myemp set hiredate=sysdate,sal=sal*1.2

where hiredate between '01-jan-81' and '31-dec-81';

where to_char(hiredate,'yyyy')=1981;

不帶條件的,是修改所有的記錄

update myemp set comm=null;

先查再删除

select * from myemp where empno=7369;

delete from myemp where empno=7369;

删除若幹個資料

select * from myemp where empno in(7566,7788,7799);

delete from myemp where empno in(7566,7788,7799);

删除也可以結合子查詢

select * from myemp order by sal desc;

delete from myemp where sal=(select max(sal) from myemp)

删除全部資料幾乎是不可能的

delete from myemp;

事務處理的概念

保證資料完整性的一種手段

具有ACID原則

保證你一個人更新資料的時候,其它人不能更新。

sessionA

sessionB

每一個session有自己獨立的事務。

緩沖區中的資料可以rollback

rollback;

commit;

更新操作被事務保護。要成功就一起成功,要失敗就退回原點重新再來。

事務鎖

兩個session進行同一條資料的操作,誰手快誰成功。

sessionA操作了,但沒送出,sessionB執行的時候會一直等待。也就是說A鎖定了這條資料,在沒有送出或回流之前,sessionB不能操作。隻能等待它送出後才能操作。

update myemp set sal=5000 where empno=7566;

update myemp set sal=90000 where empno=7566;    一直等待。

事務處理的過程中,存在行級鎖。事務的隔離性

在整個程式的世界裡,隻有兩個方法可以評價程式:時間複雜度與空間複雜度

時間換空間,不加硬體的情況下,就等吧。

空間換時間。加硬體,不加硬體的話,用雲計算,來臨時空間換時間。

在不改變現有硬體的情況下,可以利用一個周期來完成,不是一次完成。可能需要半年時間,但不影響使用者。活躍使用者與僵shi使用者。

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