oracle知識點整理

該文是本人在學習oracle視頻時整理的,MLDN李興華老師的視頻。tangyj

oracle 基本語法總結
1. oracle的總體內容
oracle的安裝及配置
sql語法:1 DML 2 DDL 3 DCL
DML:簡單查詢 ,限制查詢,分組查詢,多表查詢,子查詢,更新
DDL :創建管理數據庫
DCL:授權及回收
oracle主要用戶
sys/change_on_install:超級管理員
system/manager:普通管理員
scott/tiger:普通用戶
sqlplusw命令
set linesize 90
set pagesize 80
連接:conn scott/tiger as sysdba
一 基本語法
1 distinct 消除重複
select distinct empno from emp;
2 || 連接字符串
select '編號是:'||empno||'僱員是:'||empname from emp;
3 not null 非空查詢
select * form emp where com is not null;
4 not 整體取反
基本工資不大於1500,同時comm爲空
select * from emp where not(sal>1500 or comm is not null)
5 between and
日期之間的人員,加‘
select * from emp where hiredate between '1-1月 -81' and '31-12月 -81'
6 like 模糊查詢
% 匹配任意長度
—匹配一個長度
select * from emp where ename like '_m%'
7 不等號:<>,|=
條件>,>=,=,<,<=
二 單行函數
1 單行函數分類
字符函數:接收字符輸入並且返回字符或數值
數值函數:接收數值輸入並返回數值
日期函數:對日期類型進行操作
轉換函數:從一種數據類型轉換爲另一種數據類型
通用函數:NVL函數,DECODE 函數
2 UPPER()
將小寫字符轉爲大寫字符
select upper('smith') from dual;
3 LOWER()
select lower('SMITH') from dual;
4 INITCAP()
將單詞的第一個字符大寫
select initcap('sEEdd DDed') from dual;
5 concat()字符串連接
select concat('hello','word') from dual;
6 substr()
字符串截取
select substr('hello',1,3)
從第1位置開始截取,到第3位置結束
從0和1是一個意思
顯示僱員姓名的後3個字符
select substr(ename,length(ename)-2) from emp;
如果參數一個數字,表示從該位置截取到最後。
7 replace('hello','1','x')將hello中的l換爲x
length()取長度
8 數值操作
round():四捨五入
TRUNC():截取小數位
MOD():取餘
select round(89.222)from dual;
得到89整數
select round(789.549,2) from dual;
保留2位小數四捨五入,789.55
select round(789.534,-2) from dual;
第二個參數是負數,表示對整數四舍五 入,800
select trunc(789.532) from dual;
表示直接截取小數,不會四捨五入。789
select trunc(789.537,2) from dual;
截取小數的2位後,789.53
select trunc(789.532,-2) from dual;
截取整數,700
select mod(10,3) from dual;
去結果進行取餘,1
9 日期函數
日期-數字=日期
日期+數字=日期
日期-日期=數字
sysdate表示系統時間
select sysdate from dual;
求出10部門僱員進入公司的星期數
select ename,round((sysdate-hiredate)/7) from emp;
10 oracle中的日期支持函數
MONTHS_BETWEEN():求出給定日期之間的月數
ADD_MONTHS():在指定的日期上加上指定的月數,求出之後的日期
NEXT_DAY():下一個星期幾是哪一個日期
LAST_DAY():求出給定日期的最後一天日期
select ename,MONTH_BETWEEN(SYSDATE,HIREDATE)from emp;
結果中會包含小數點,需要用round去掉
select add_months(sysdate,4)from dual;
select next_day(sysdate,'星期一') from dual;
select last_day(sysdate)from dual;
求出當前日期中月的最後一天
11 轉換函數
TO_CHAR():轉換爲字符串
TO_NUMBER():轉換爲數字
TO_DATE():轉換爲日期
12 select ename,TO_CHAR(hiredate,'yyyy') year,TO_CHAR(hiredate,'mm') months,TO_CHAR(hiredate,'dd') day
from emp;
單獨拿出日期中的年月日顯示
select TO_CHAR(hiredate,'yyyy-mm-dd')from emp;
fm的用法
12 select ename,TO_CHAR(SAL,'99,9999')from emp;
按照指定的格式顯示sal
select ename,TO_CHAR(sal,'$99,9999');
13 select to_number('22')+to_number('2') from dual;
結果是24
14 select TO_DATE('2009-02-16','YYYY-MM-DD') FROM DUAL;
將字符串按照日期格式轉換,但後面的不是轉換後的格式,而是字符串的格式,轉換後爲系統自己的日期格式。
15 NVL ()將null的值轉爲指定類型
select ename,NVL(COMM,O) FROM EMP;
將comm字段爲空的轉爲0
16 DECODE ()類似於 if elseif else
select ename,DECODE(job,'clerk','1','slaemane','2','mangetr','3') from emp;
函數的意思是查詢job字段,如果爲clerk顯示1,爲mangert顯示3
17 sign()函數根據表達式的值是0、正數還是負數,分別返回0、1、-1;

select decode(sign(to_number(to_char(sysdate,'MM'))-6),1,'下半年',-1,'上半年',0,'六月') as MM from dual;

18 decode 和case when 比較
SELECT DECODE(OWNER, 'SYSTEM', 'SYSTEM', 'SYS', 'SYSTEM', 'USER') from emp;

6075760 rows selected.

Elapsed: 00:00:07.24

SELECT CASE OWNER WHEN 'SYSTEM' THEN 'SYSTEM'
WHEN 'SYS' THEN 'SYSTEM'
ELSE 'USER' END
FROM emp;

6075760 rows selected.

Elapsed: 00:00:07.22

19 select distinc job from emp where com is not null;
(select * from emp where comm is null or comm<500)
(select * from emp where hidaerate =last_day(hiredate)-2)
早於12年前受僱
select * from emp where ROUND(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12)>=12
首字母大寫
select initcap(ename) from emp;
5個字符員工
select * from emp where length(ename)=5;
顯示不帶R的員工姓名
select * from emp where ename not like '%R%;
所有員工姓名的前三個字符
select substr(enam,1,3) from emp;
顯示員工姓名,用A 代替a
select replace(ename,'a','A') FROM EMP;
顯示服務滿10年服務員的姓名和僱傭日期
select ename,hiredate from emp where months_between(sysdate,hiredate)>10
顯示員工的信息,按姓名排序
select * from emp order by ename;
顯示員工姓名和受僱日期,老員工排在前面
select ename,hiredate from emp order by hiredate ;
顯示員工姓名工作薪金,按工作降序排序,若工作相同,按薪金排序
select ename,job,sales from emp order by job desc,sales;
顯示所有員工的姓名,加入公司的年份和月份,按受僱日期所在月排序,月份相同則最早年份在上面
select ename,to_char(hiredate,'yyyy') y,to_char(hiredate,'mm') m from emp order by m,y;
顯示員工的日薪資,忽略餘數
select enamel,round(sal/30) from emp;
找出2月受聘的所有員工
select * from emp
where to_char(hiredate,'mm')='2';
顯示員工加入公司的天數
select ename,sysdate-hiredate from emp;
以年月日的方式顯示所有員工的服務年限
select ename ,trunc(months_between(sysdate,hiredate)/12)year,mod(months_between(sysdate,hiredate),12) month,mod(sysdate-hiredate,30)dd from emp;
多表查詢
查詢出僱員的姓名,工資,部門名稱,工資在公司的等級
select e.ename,e.sal,d,dname,s.gradefrom emp e,dept d,salgrade s

where e.deptno=d.deptno and e.sal between s.local and s.high;




oracle中join和union 的語法總結
1.join
inner join cross join left join right join
其中left join表示 +在等號右邊,右邊強制有空,right join 表示+在等號左邊,左邊強制爲空。
spacer.gif
spacer.gif
spacer.gif
spacer.gif
spacer.gif
oracle union union all intersect minus

1.union :得到兩個結果的並集,並且自動去掉重複行。不會排序
2.union all:得到兩個查詢結果的並集,不會去掉重複行。不排序
3.intersect:得到兩個查詢結果的交集,並且按照結果集的第一個列進行排序。
4.ninus:得到兩個查詢結果的減集,以第一列進行排序

spacer.gif


函數和存儲過程的區別
create or replace procedure add_emailinfo(namee email_info.fullname%type ,address email_info.email_address%type )

is

begin

insert into email_info(fullname,email_address) values (namee,address);

end;

//調用過程

call add_emailinfo('cherry','asdfsdf');

/////////////////////////////////////////////////////////////////////////////////////

//創建函數

create or replace function sel_emailinfo(namee email_info.fullname%type )

return varchar2 is

address varchar2(30);

begin

select email_address into address from email_info

where trim(fullname)=trim(namee);

return address;

end ;

//調用函數

select sel_emailinfo('bbb') from dual;

spacer.gif

本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文鏈接:http://www.linuxidc.com/Linux/2012-09/70652.htm



1.sql語句處理的四個階段
open-parse-bind-execute-fetch-close
sql tunning的重點
SQL:insert update delete select
關注select
關注:如何用最小的硬件資源消耗、最少的響應時間定位數據位置
減少服務器資源消耗(磁盤IO)
查詢儘量用確定的列名,少用*號。select count(key)from tab where key>0 性能優於select count(*)from tab;
儘量少嵌套子查詢,這種查詢會消耗大量的cpu資源。對於有比較多的or運算的查詢,建議分成多個查詢,用union all聯結起來。將記錄少的放在右面
帶有distinct union minus intersect order by的SQL語句會啓動sql引擎執行耗費資源的排序功能。
這些功能都可以用別的方式代替
用exists替換distinct
select distinct dept_no,dept_name from dept d,emp e where d.dept_no=e.dept_no;
select dept_no,dept_name from dept d
where exists(select 'x' from emp e where e.dept_no=d.dept_no);
可以的話用union all 替換union

oracle中sql語句的優化(轉帖)


一、執行順序及優化細則

1.表名順序優化
(1) 基礎表放下面,當兩表進行關聯時數據量少的表的表名放右邊
表或視圖:
Student_info (30000條數據)
Description_info (30條數據)
select *
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'

select *
from student_info si--學生信息表
,description_info di
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
以student_info作爲基礎表,你會發現運行的速度會有很大的差距。


(2) 當出現多個表時,關聯表被稱之爲交叉表,交叉表作爲基礎表
select *
from description_info di
,description_info di2
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.school_id = di.lookup_code(+)
and di.lookup_type(+) = 'SCHOOL_ID'

select *
from student_info si--學生信息表
,description_info di
,description_info di2
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.school_id = di.lookup_code(+)
and di.lookup_type(+) = 'SCHOOL_ID'
以student_info作爲基礎表,你會發現運行的速度會有很大的差距,
當基礎表放在後面,這樣的執行速度會明顯快很多。

2.where執行順序
where執行會從至下往上執行
select *
from student_info si --學生信息表
where si.school_id=10 --學院ID
and si.system_id=100--系ID
擺放where子句時,把能過濾大量數據的條件放在最下邊

3. is null 和is not null
當要過濾列爲空數據或不爲空的數據時使用
select *
from student_info si --學生信息表
where si.school_id is null(當前列中的null爲少數時用is not null,否則is null)

4.使用表別名
當查詢時出現多個表時,查詢時加上別名,
避免出現減少解析的時間字段歧義引起的語法錯誤。

5. where執行速度比having快
儘可能的使用where代替having
select from student_info si
group by si.student_id
having si.system_id!=100
and si.school_id!=10
(select from student_info si
wehre si.system_id!=100
and si.school_id!=10
group by si.student_id)

6. * 號引起的執行效率
儘量減少使用select * 來進行查詢,當你查詢使用*,
數據庫會進行解析並將*轉換爲全部列。


二、替代優化
1、用>=替代>
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=10

select ui.user_name
from user_info ui--員工信息表
where ui.student_id>9
執行時>=會比>執行得要快

2、用UNION替換OR (適用於索引列)
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2
上面語句可有效避免全表查詢
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
or ui.student_id=2
如果堅持要用OR, 可以把返回記錄最少的索引列寫在最前面

3、用in 代替or
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
or ui.student_id=20
or ui.student_id=30
改成
select ui.user_name
from user_info ui--員工信息表
where ui.student_id in (10,20,30)
執行會更有效率

4、 Union All 與Union
Union All重複輸出兩個結果集合中相同記錄
如果兩個並集中數據都不一樣.那麼使用Union All 與Union是沒有區別的,
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union All
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2

select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2
但Union All會比Union要執行得快

5、分離表和索引
總是將你的表和索引建立在另外的表空間內
決不要將這些對象存放到SYSTEM表空間裏

三、一些優化技巧


1、計算表的記錄數時

select count(si.student_id)
from Student_info si(student_id爲索引)

select count(*) from Student_info si
執行時.上面的語句明顯會比下面沒有用索引統計的語句要快

2.使用函數提高SQL執行速度

當出現複雜的查詢sql語名,可以考慮使用函數來提高速度
查詢學生信息並查詢學生(李明)個人信息與的數學成績排名

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.description = '李明'

而且我們將上面order_num排名寫成一個fuction時
create or replace package body order_num_pkg is
function order_num(p_student_id number) return_number is
v_return_number number;
begin
select res.order_num --排名
into v_return_number
from result res
where res.student_id = di.student_id
order by result_math;
return v_return_number;
exception
when others then
null;
return null;
end;
end order_num_pkg;
執行
select di.description student_name
,order_num_pkg.order_num(di.student_id) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.description = '李明'
執行查詢時的速度也會有所提高

3.減少訪問數據庫的次數

執行次數的減少(當要查詢出student_id=100的學生和student_id=20的學生信息時)
select address_id
from student_info si --學生信息表
where si.student_id=100

select address_id
from student_info si --學生信息表
where si.student_id=20
都進行查詢.這樣的效率是很低的
而進行
(
select si.address_id,si2.address_id
from student_info si --學生信息表
,student_info si2
where si.student_id=100
and si2.student_id=20

select decode(si.student_id,100,address_id)
,decode(si.student_id,20,address_id)
from student_info si
)
執行速度是提高了,但可讀性反而差了..
所以這種寫法個人並不太推薦

4、用Exists(Not Exists)代替In(Not In)

在執行當中使用Exists或者Not Exists可以高效的進行查詢

5、Exists取代Distinct取唯一值的

取出關聯表部門對員工時,這時取出員工部門時,出現多條..
select distinct di.dept_name
from departments_info di --部門表
,user_info ui --員工信息表
where ui.dept_no = di.dept_no
可以修改成
select di.dept_name
from departments_info di --部門表
where exists (select 'X'
from user_info ui --員工信息表
where di.dept_no = ui.dept_no)
6、用表連接代替Exists
通過表的關聯來代替exists會使執行更有效率
select ui.user_name
from user_info ui--員工信息表
where exists (select 'x '
from departments_info di--部門表
where di.dept_no = ui.dept_no
and ui.dept_cat = 'IT');
執行是比較快,但還可以使用表的連接取得更快的查詢效率
select ui.user_name
from departments_info di
,user_info ui --員工信息表
where ui.dept_no = di.dept_no
and ui.department_type_code = 'IT'

代碼是經測試並進行優化所寫,
以上只例子,具體使用還是要針對各個不同的具體的業務使用用Exists(Not Exists)代替In(Not In)

四、索引篇

1、運算導致的索引失效

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.student_id+0=100/*student_id索引將失效*/

2、類型轉換導致的索引失效

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id='100'

student_id爲number類型的索引,當執行下列語句,
oracle會自動轉換成
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id=to_number('100')
所幸,只是解析並轉換類型,並沒有導到失效,
但要是寫成下面,將會使用其失效
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and to_char(di.student_id)='100'

3、在索引列上進行計算引起的問題

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id-2=10
在索引列中進行運算,將會不使用索引而使用全表掃描
而將
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id=10+2
將會得到高效的運行速度

4、 Is not null引起的問題(student_id爲索引)

不要把存在空值的列做爲索引,否則無法使用索引
select ui.user_name
from user_info ui--員工信息表
where ui.student_id is not null--索引失效

select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=-1--索引有效

5、Order by導致索引失效(student_id爲索引)

select ui.user_name
from user_info ui--員工信息表
group by ui.student_id
而使用
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=-1
將使其有效,
在order by中只存在兩種條件下可以使用索引
(ORDER BY中所有的列必須包含在相同的索引中並保持在索引中的排列順序
ORDER BY中所有的列必須定義爲非空. )

6、自動選擇索引

如果表中有兩個以上(包括兩個)索引,其中有一個唯一性索引,而其他是非唯一性.
在這種情況下,ORACLE將使用唯一性索引而完全忽略非唯一性索引.

7、 !=導致索引失效

select ui.user_name
from user_info ui--員工信息表
where ui.student_id!=0
在Where中使用!=將會把索引失效

8、%導致的索引失效

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.look_code Like '%12'/*look_code爲索引,索引將失效*/

select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.look_code Like '12%'/*索引有效*/
以上只例子,具體還是要針對各個不同的具體的業務使用

五、oracle 中的not Exists與Not in的性能巨大差異

Not Exists與Not in的作用同樣是排除數據,在oracle 中使用not in並不象mysql中的執行那麼快,如(
select jt1.doc_num --單據號碼
,oalc.description school_name --學校名稱
,oalc2.description system_name --系名稱
,oalc.description class_name --班級名稱
from java_table1 jt1
,java_table_description oalc
,java_table_description oalc2
,java_table_description oalc3
where oalc.lookup_type(+) = 'JAVA_SCHOOL_NAME'
and jt1.school_id = oalc.lookup_code(+)
and oalc2.lookup_type(+) = 'JAVA_SYSTEM_NAME'
and jt1.system_id = oalc2.lookup_code(+)
and oalc3.lookup_type(+) = 'JAVA_CLASS_NAME'
and jt1.class_id = oalc3.lookup_code(+)
and not exists
(select jt2.header_id
from java_table2 jt2 jt1.header_id = jt2.header_id))

select jt1.doc_num --單據號碼
,oalc.description school_name --學校名稱
,oalc2.description system_name --系名稱
,oalc.description class_name --班級名稱
from java_table1 jt1
,java_table_description oalc
,java_table_description oalc2
,java_table_description oalc3
where oalc.lookup_type(+) = 'JAVA_SCHOOL_NAME'
and jt1.school_id = oalc.lookup_code(+)
and oalc2.lookup_type(+) = 'JAVA_SYSTEM_NAME'
and jt1.system_id = oalc2.lookup_code(+)
and oalc3.lookup_type(+) = 'JAVA_CLASS_NAME'
and jt1.class_id = oalc3.lookup_code(+)
and jt1.header_id not in (select jt2.header_id from java_table2 jt2)

當jt2表中的數據比較大時,就會出現巨大的差異,以上只能是我的個人理解與測試結果(java_table1 視圖測試

數據量爲36749,java_table2 爲300條),如有其它可相互討論




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章