SQL基礎

ORACLE

	|-入門語句
			|-數據庫連接
					|-普通用戶連接:Conn scott/tiger
					|-超級管理員連接:Conn sys/sys as sysdba
					|-斷開連接:Disconnect
			
			|-SQL操作
					|-保存SQL文件:Save c:\1.txt
					|-編輯SQL語句:Ed c:\1.txt
					|-運行SQL語句:@ c:\1.txt
					|-顯示錶結構:Desc tableName;
					|-查看用戶下的所有對象: Select * from tab;
			
			|-系統表操作		
					|-查詢指定名稱表信息:select owner, object_name, status from dba_objects where object_name like '%DUAL%'		
					
					
	|-單行函數 
			|-字符函數
					|-Upper
					|-Lower
					|-Initcap
							|-將字符串首字母變成大寫
					|-concat
							|-concat('a', 'b')= 'a'||'b' --> 'ab'
					|-substr
							|-substr( string, start_position, [ length ] )
					|-replace
							|-replace('Abc', 'a', 'A') --> 'abc'
					|-instr
							|-instr(源串,目標串[,開始位置[,第幾次出現]])		
					|-lpad/ rpad
							|-lpad(源串,數量,數量不足的時候填充的字符串);
							|-select lpad('yao', 10, 'fuck') from dual; --> 'fuckfucyao'
					|-trim
			|-數值函數
					|-Round
							|-ROUND(指定數值, 指定位數)
									|-例:select round(412, -2), round(412.313, 2) from dual; --> 400, 412.31
					|-Mod
							|-Mod(n1, n2) --> n1%n2
					|-Trunc
							|-意爲截斷,不進行四捨五入操作
									|-日期型
										|-select trun(sysdate, 'mm' from dual;	--> 01-7月 -12
										|-select trun(sysdate, 'dd' from dual;	--> 23-7月 -12
									|-數值型
										|-select trunc(89.986, 2) from dual;	-->	89.98
			|-日期函數
					|-Months_between
							|-select sysdate, to_date('20120612', 'yyyymmdd'), months_between(sysdate, to_date('20120612', 'yyyymmdd')) from dual; -->	1.38223118
					|-Add_months
							|-select sysdate, add_months(sysdate, 1) from dual;	--> 	2012-07-23, 2012-08-23
					|-Next_day
							|-下一個指定星期:select sysdate, next_day(sysdate, '星期四') from dual;	-->	2012-07-23 星期一, 2012-07-26 星期四
					|-last_day
							|-該月最後一天:select last_day(sysdate) from dual;	-->	2012-07-31
			|-轉換函數
					|-to_char
							|-to_char(sysdate, 'yyyy')	-->	2012
							|-to_char(sysdate, 'fmyyyy-mm-dd')	-->	2012-07-23
							|-to_char(111.1, 'L999, 999, 999')	-->	¥999
					|-to_number
							|-select to_number('13')+ to_number('14') from dual;
					|-to_date
							|-select to_date('20120723', 'yyyymmdd') from dual;
			|-通用函數
					|-NVL
							|-空值時設置爲默認值:select nvl(null, 0), nvl(111, 0) from dual;	-->	0, 111;
					|-NULLIF
							|-相等返回NULL,否則返回第一個值:select nullif(0,0), nullif(11,12) from dual;	-->	null, 11;
					|-NVL2
							|-值1爲空返回值3,否則返回值2:select nvl2(null,1,2), nvl2(1,1,2) from dual;	-->	2, 1
					|-CLALESCE
							|-返回第一個非空值,參數爲同類型(!!)無限數量:select coalesce(null, null, 1, null, 2) from dual;
					|-CASE
							|-select empno, ename, case deptno when 1 then '財務部' when 2 then '外交部' when 3 then '開發部'	else 'FBI'	end as 部門 from emp;
					|-DECODE
							|-與CASE一般用途:select empno, ename,decode(deptno, 1,'財務部', 2, '外交部', 3, '開發部', 'FBI') as 部門 from emp;
							
							
	
	
	|-多表查詢
			|-笛卡爾集
					|-select * from emp, dept;
			|-等值連接
					|-select dname, ename, hiredate from emp, dept where emp.deptno= dept.deptno;
			|-非等值連接
					|-笛卡爾集的基礎上進行條件判斷:select ename, empno, grade, sal, losal, hisal from emp, salgrade where sal between losal and hisal;
			|-自連接
					|-select e.ename, m.empno from emp e, emp m where e.mgr= e.empno;
			|-左外聯接
					|-select s.sname, t.tname from student s, teacher t where s.ssex= t.tsex(+)
					|-select s.sname, t.tname from student s left join teacher t on s.ssex= t.tsex
			|-右外聯接
			|-滿外聯接
					|-select s.sname, t.tname from student s full outer join teacher t on s.ssex= t.tsex
					
	|-集合操作
			|-UNION
					|-並集,顯示所有,但重複項只顯示一次
			|-UNION ALL
					|-並集,顯示所有,包括重複項
			|-INTERSECT
					|-交集,只顯示重複項
			|-MINUS
					|-差集,只顯示對沒有的,與順序有關
					


	|-子查詢
			|-單行子查詢
					|-select * from student where sage >(select sage from student where sid= 80308100);
					|-子查詢結果爲空時無返回結果
					|-子查詢返回多行時報錯
			|-多行子查詢
					|- SELECT * FROM TABLEA WHERE FLD > ALL(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD > (SELECT MAX(FLD) FROM TABLEA)
					|- SELECT * FROM TABLEA WHERE FLD > ANY(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD > (SELECT MIN(FLD) FROM TABLEA)
					|-  SELECT * FROM TABLEA WHERE FLD = ANY(SELECT FLD FROM TABLEA) == SELECT * FROM TABLEA WHERE FLD IN (SELECT FLD FROM TABLEA)
			|-分頁查詢
					|-select * from (select rownum no, e.* from (select * from emp order by sal desc) e where rownum<= 5) where no>= 3;
			|-EXISTS
					|-select * from student s where exists (select null from teacher t where t.tage> 2* s.sage);
					|-注意事項
							|-子查詢記錄少,主查詢表大且有索引時用IN,反之用EXISTS
							
							
	|-高級查詢
			|-隨機返回指定數量的記錄
					|-SELECT * FROM (SELECT * FROM student ORDER BY dbms_random.value()) WHERE ROWNUM<= 2;
			|-排序的時候進行空值優先順序
					|-SELECT * FROM student ORDER BY sname NULLS FIRST;
			|-爲行指定行標記,不同於行序ROWNUM
					|-SELECT * FROM (SELECT row_number() over (ORDER BY sname) rn, sname FROM student) s WHERE MOD(rn, 2)= 1;
			|-同時查詢最大最小值
					|-SELECT MAX(sage) over(), MIN(sage) over() FROM student;
			|-連續求和
					|-SELECT sname, sage, SUM(sage) over(), SUM(sage) over(ORDER BY sname) FROM student;
						|-SUM(sage) over()= SUM(sage),但可用於非聚合語句中
						|-SUM(sage) over(ORDER BY sname),在sname的層次上逐個添加
							|-   	SNAME	SAGE	SUM(SAGE)OVER()	SUM(SAGE)OVER(ORDERBYSNAME)
									1	潘巧容	23		57							23
									2	王老吉	10		57							33
									3	姚清居	24		57							57
									4				 			57    						57
			|-分組求和
					|-SELECT sname, ssex, sage, SUM(sage) over(PARTITION BY ssex ORDER BY sname) FROM student;
						|-   	SNAME	SSEX		SAGE	SUM(SAGE)OVER(PARTITIONBYSSEXO
								1	test		男		99		99
								2	姚清居	男		24		123
								3	female	女		33		33
								4	潘巧容	女		23		56
								5	王老吉	中性	10		10
								6								88		88
			|-得到上行記錄和下行記錄
					|-SELECT 
								sname, sage, 
								lead(sage) over(ORDER BY sage) nextAge, 
								lag(sage) over(ORDER BY sage) frontAge 
						FROM student;				
			|-根據子串分組
					|-SELECT to_char(tmp_date, 'yyyy'), AVG(tmp_id) 
						FROM temp 
						GROUP BY to_char(tmp_date, 'yyyy');				
			|-確定一年的天數
					|-SELECT add_months(trunc(SYSDATE, 'y'), 12) - trunc(SYSDATE, 'y') FROM dual;
			|-查詢每個性別下最年輕的前兩位的信息
					|-SELECT * FROM (
						       SELECT sname, ssex, sage, row_number() over(PARTITION BY ssex ORDER BY sage) rn
						       FROM student
						)
						WHERE rn< 3;
					|-SELECT sname, ssex, sage 
						FROM student s1
						WHERE (
						  SELECT COUNT(1)
						  FROM student s2
						  WHERE s1.ssex= s2.ssex AND s1.sname!= s2.sname AND s2.sage< s1.sage
						)< 2
						ORDER BY ssex, sage;
	|-數據字典
			|-查詢用戶權限表
					|-SELECT * FROM All_Tables WHERE owner= 'YQJ';
			|-查看指定用戶擁有的指定表單的所有字段完整信息
					|-SELECT * FROM all_tab_columns WHERE table_name= 'STUDENT' AND owner= 'YQJ';
			|-查詢表索引
					|-SELECT * FROM sys.All_Ind_Columns WHERE table_name= 'STUDENT';
			|-查詢表約束
					|-SELECT * FROM all_constraints WHERE table_name= upper('student');
			|-查詢Oracle中描述數據字典視圖
					|-SELECT table_name, comments FROM DICTIONARY WHERE table_name LIKE '%TABLE%';
			
			
	|-Oracle體系結構(DBA)
			|-數據庫
					|-一系列物理文件(數據文件,控制文件,重做日誌文件,聯機日誌等)的集合與對應的邏輯結構(表空間、段、區、塊等)
			|-數據庫實例
					|-內存結構
							|-SGA
							|-PGA
					|-後臺進程
	
	
	|-DDL- 改變表結構
			|-建表
					|-自定義表結構
						CREATE TABLE person(
							pID NUMBER(10),
							pName VARCHAR2(30),
							pSex VARCHAR2(10)
						)TABLESPACE yqj;	--不寫默認創建在當前用戶的表空間上
					|-在已有表基礎上進行結構和數據搭建
						CREATE TABLE employ
						AS SELECT 0 AS sel, person.* FROM person;*
			|-新增字段
					|-ALTER TABLE EMPLOY ADD eage NUMBER(5);
			|-修改字段屬性
					|-ALTER TABLE employ MODIFY eage NUMBER(10);
			|-修改字段名稱
					|-ALTER TABLE employ RENAME COLUMN psex TO esex;
			|-刪除字段
					|-ALTER TABLE employ DROP COLUMN test;
			|-清空表數據
					|-TRUNCATE TABLE employ;
			|-表重命名
					|-RENAME employ TO zhiyuan;
					
					
	|-DML- 改變數據結構
			|-插入
					|-INSERT INTO aaa(sid, sname, ssex, sage, saddress)
						SELECT sid, sname, ssex, sage, saddress FROM student WHERE ssex= '中性'
			|-更新
					|-UPDATE aaa
						SET(sname, saddress)=
							(SELECT sname||'2', saddress||'2' FROM aaa WHERE sid= 80308101)
						WHERE sid= 80308100
			|-刪除
					|-DELETE FROM aaa WHERE sid= 80308100;
			|-有更沒插
					|-MERGE INTO aaa
						USING student	--這個標註了範圍
						ON(aaa.sid= student.sid)
						WHEN MATCHED THEN
						UPDATE SET sname= student.sname, ssex= student.ssex, saddress= student.saddress
						WHEN NOT MATCHED THEN
						INSERT(sid, sname, ssex, sage, saddress) VALUES(student.sid, student.sname, student.ssex, student.sage, student.saddress)
						;
			
	|-約束
			|-例
					|-CREATE TABLE constraintExamp(
						 cID NUMBER PRIMARY KEY,
						 cName VARCHAR(30) NOT NULL,
						 cTel VARCHAR2(50) UNIQUE,
						 cAge NUMBER CHECK(cAge BETWEEN 0 AND 150),
						 cCountryID NUMBER REFERENCES country(cCountryID) ON DELETE CASCADE
						);
			|-非空約束
					|-NOT NULL
					|-限制該項不爲置空
			|-主鍵約束
					|-PRIMARY KEY
					|-不能重複,不能爲空
			|-唯一約束
					|-UNIQUE
					|-值不能重複,空值除外
			|-條件約束
					|-CHECK
					|-插入數據必須滿足特定條件
			|-外鍵約束
					|-指定該項值取自指定表的列值kwkw
					|-cCountryID NUMBER REFERENCES country(cCountryID)
					|-CONSTRAINT constraintExamp_cCountryID_fk FOREIGH KEY(cCountryID) REFERENCES COUNTRY(cCountryID)
			|-級聯刪除
					|-主表信息刪除後,自動進行關聯表的信息清除
					|-ON DELETE CASCADE
			
		|-增加約束
				|-ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cID_pk PRIMARY KEY(cid);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cTel_uk UNIQUE(cTel);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT constraintExamp_cAge_ck CHECK(cage BETWEEN 0 AND 150);
					ALTER TABLE CONSTRAINTEXAMP ADD CONSTRAINT country_constraintExamp_cCountryID_fk FOREIGN KEY(cCountryID) REFERENCES country(cCountryID) ON DELETE CASCADE;
		|-刪除約束
				|-ALTER TABLE CONSTRAINTEXAMP DROP CONSTRAINT constraintExamp_cID_pk;
		|-啓用約束
				|-ALTER TABLE CONSTRAINTEXAMP ENABLE CONSTRAINT constraintExamp_cID_pk;
		|-禁用約束
				|-ALTER TABLE CONSTRAINTEXAMP DISABLE CONSTRAINT constraintExamp_cID_pk;
				
				
				
	|-視圖
		|-概念:封裝了各種複雜查詢的語句
			|-創建視圖
					|-CREATE VIEW 視圖名稱(字段) AS 子查詢
					|-CREATE OR REPLACE VIEW maleStudent (sid, sname, ssex, sage, saddress)
						AS 
						SELECT sid, sname, ssex, sage, saddress
						FROM student
						WHERE ssex= '男'
						WITH CHECK OPTION CONSTRAINT maleStudent_ck;
						--WITH READ ONLY;
			|-更新視圖
					|-UPDATE maleStudent SET ssex= '';
					|-注意會聯動更新原表記錄
			|-保護視圖的創建規則
					|-保護WHERE語句中的字段不被修改
					|-WITH CHECK OPTION CONSTRAINT maleStudent_ck
			|-只讀
					|-設置任意字段都不可更改,視圖爲只讀
					|-WITH READ ONLY
			|-查看視圖
					|-SELECT * FROM maleStudent;
			
			
			
	|-索引
			|-定義
					|-用於提升查詢效率的數據庫對象
					|-通過快速定位數據的方法來減少磁盤I/O操作
					|-索引信息與表獨立存放
					|-Oracle數據庫自動使用和維護索引
			|-分類
					|-唯一性索引
					|-非唯一性索引
			|-創建方式
					|-自動創建
							|-在定義主鍵和唯一鍵時系統自動在相應字段上創建唯一性索引
					|-手動創建
							|-用戶選擇在其它列上創建非唯一索引,以加速查詢速度
			|-查詢方式
					|-查詢現有的索引信息:SELECT * FROM user_indexes;
					|-查詢索引建立在哪些字段上:SELECT * FROM user_ind_columns;
			|-優缺點
					|-優點
							|-極大加快數據的檢索速度
							|-創建唯一性索引,保證數據庫中第一行數據的唯一性
							|-加速表和表之間的連接
							|-使用分組和排序子句進行檢索時,明顯減少查詢速度
					|-缺點
							|-索引需要佔用物理空間
							|-當對錶中數據進行增刪改時,索引亦需動態維護,降低數據維護速度
			|-創建原則
					|-select佔多的表上
					|-where語句中出現頻率最高的列
					|-小於5M的表,最好不要使用索引查詢,表越小越適合用全表掃描
			|-使用原則
					|-複合索引按f1,f2,f3次序建立,where語句中若無f2= '1',會因f2不是索引第一個字段而無法進行索引查詢
					|-索引查詢避免任何形式計算,並將操作移到等號右邊
					|-如下操作會顯式阻止Oracle使用索引:is(not) null, not in, !=, like, numeric_col+ 0, date_col+ 0; char_col||'', to_char, to_number, to_date;
			|-創建索引
					|-CREATE INDEX student_index ON student(sid, sname);
					|-注:建立索引時,組合的順序關係非常重要
			|-索引存儲
					|-索引和表獨立存在,建議兩種不要放置於同一表空間,從而避免IO衝突。
			|-刪除索引
					|-DROP INDEX student_index ;
			|-管理索引
					|-先插入數據後再創建索引
					|-爲索引指定表空間		
			
			
	|-SQL優化
			|-實質
					|-在結果正確的前提下,
							用優化器可識別的語句,
							充分利用索引,
							執行過程中訪問儘量少的數據塊,減少表掃描的I/O次數,
							儘量避免全表掃描和其它額外開銷。
			|-優化器
					|-RBO- rule-based-opimizer
							|-根據自己內部設定的規則進行
					|-CBO- cost-based-opimizer
							|-建議使用,更多地根據表及索引的狀態信息來選擇計劃
			|-儘量少用IN,而用EXISTS代替
					|-主大子小用IN,主小子大用EXISTS
			|-用NOT EXISTS或外連接代替NOT IN
					|-因爲NOT IN不能應用表的索引
			|-儘量不用<> 或者!= 操作符
					|-不等於操作符永遠不會用到索引,對它的處理只會產生全表掃描
			|-設計表的時候,將索引列設置爲NOT NULL
					|-判斷字段是否爲空是不會應用到索引的,因爲B樹索引是不索引空值的
			|-儘量不用能配符"%"或 "_"做爲查詢字符串的第一個字符
					|-出現如上的情況時,索引是不會被使用的
			|-WHERE子句中避免在索引列上使用計算
					|-如果索引並非基於函數的,那麼當在Where子句中對索引列使用函數時,索引不再志作用
			|-用">="替代">"
					|-A>2時,ORACLE會先找出爲2的記錄索引再進行比較,而A>=3時ORACLE則直接找=3的記錄索引
			|-利用SGA共享池,避開parse階段
					|-不同區域出現的相同SQL語句要保證查詢字符完全相同,建議經常使用的用常量代替,以利用SGA共享池,避開parse階段,防止相同的sql語句被多次分析
					|-其中存儲過程就是提高效率的一種有效方法
			|-WHERE後面的條件順序要求
					|-表連接語句寫在最前面,可以過濾掉最大數量記錄的條件居後
			|-使用表的別名,並將之作爲每列的前綴
					|-連接多表時,使用表別名並作爲列前綴,可以減少解析時間
			|-進行顯式或隱式運算的字段不能進行索引
					|-所以與索引列進行比較的時候,只進行結果比較,不對索引列進行數值計算
			|-用UNION ALL代替UNION
					|-UNION會進行SORT UNIQUE,即數據唯一性校驗,但實質連接的一般不會出現重複記錄,所以可以採用UNION ALL,不排除重複記錄行,效率可以更高
			|-改變ORACLE的SGA的大小
					|-定義
							|-數據庫的系統全局區
					|-組成
							|-共享池+ 數據緩衝區+ 日誌緩衝區
					|-共享池
							|-共享SQL區
									|-專門存放用戶SQL命令,使用最近最少使用等優先級算法來更新覆蓋
							|-數據字典緩衝區
									|-存放數據庫的動態信息
									|-DBA可查看這些內存的命中率以從數據庫的角度對數據庫性能調優
											|-查看共享區SQL的重用率:SELECT (SUM(pins- reloads))/ SUM(pins) AS "Lib Cache" FROM v$librarycache;
													|-低於90%時建議增加共享池大小
											|-查詢數據字典緩衝區的命中率:SELECT (SUM(gets- getmisses- USAGE- fixed)/ SUM(gets)) AS "Row Cache" FROM v$rowcache;
													|-同樣最好在90%以上,否則建議增加共享池大小
					|-數據緩衝區
							|-存放SQL運行結果到抓取到data block
									|-查看數據庫緩衝區的使用情況SELECT NAME, VALUE FROM v$sysstat WHERE NAME IN('db block gets', 'consistent gets', 'physical reads');
											|-查看數據緩衝區的命中率:SELECT 1- (SUM(CASE WHEN NAME= 'physical reads' THEN VALUE ELSE 0 END) /(SUM(CASE WHEN NAME= 'consistent gets' THEN VALUE ELSE 0 END)+ SUM(CASE WHEN NAME= 'db block gets' THEN VALUE ELSE 0 END)))  FROM v$sysstat
													|-最好在90%以上,否則建議增加數據緩衝區大小
					|-日誌緩衝區
							|-存放數據庫生成的日誌
									|-查看日誌緩衝區的使用情況:SELECT NAME, VALUE FROM v$sysstat WHERE NAME IN ('redo entries', 'redo log space requests');
											|-計算日誌緩衝區的申請失敗率:SELECT SUM(CASE WHEN NAME= 'redo log space requests' THEN VALUE ELSE 0 END)/ SUM(CASE WHEN NAME= 'redo entries' THEN VALUE ELSE 0 END) FROM v$sysstat;
													|-失敗率應接近0,否則說明日誌緩衝區太小,需要增加。
			
			
	|-序列、同義詞
			|-序列
					|-創建序列
							|-CREATE SEQUENCE temp_sq
								START WITH 1
								INCREMENT BY 1
								ORDER 
								CACHE 20 --可以關閉NOCACHE,但進行內存緩衝對性能有所提高
								NOCYCLE; --確保該序列用於多表的情況下,ID是唯一的	--CYCLE MAXVALUE 10,即到10後重新從1開始
					|-讀取數值
							|-SELECT temp_sq.nextval FROM dual;
								SELECT temp_sq.currval FROM dual;	--必須調用nextval後才能使用currval
					|-改變增量
							|-注:不能改變當前值,只能改變增量:ALTER SEQUENCE temp_sq INCREMENT BY 3;
						|-實現表ID自增
								|-CREATE SEQUENCE temp_sq
									START WITH 1
									INCREMENT BY 1
									CACHE 20
									NOCYCLE;
									
									CREATE OR REPLACE TRIGGER trg_temp_insert
									BEFORE INSERT
									ON temp
									FOR EACH ROW
									BEGIN
									    SELECT temp_sq.nextval INTO :new.tmp_id FROM dual;
									END;
			|-同義詞
					|-概念
							|-方便操作不同用戶下的對象
							|-使兩個應用程序使用不同的名字指向同一張表
							|-使不同用戶指向同一張表
					|-創建同義詞
							|-CREATE PUBLIC SYNONYM student FOR sys.student;
					|-刪除同義詞
							|-DROP PUBLIC SYNONYM student;
							
							
							
	|-PL SQL
			|-PL/SQL塊
					|-DECLARE
						    eNO student.sid%TYPE;   --指定表中對應列類型
						    stu student%ROWTYPE;    --表結構的複合類型
						    eName VARCHAR2(30);     --此處只是展示使用方法,並無實際用途
						BEGIN
						    eNO:= &請輸入學號信息;         --進行數據錄入,其中&後面爲界面顯示名稱
						    SELECT * INTO stu FROM  student WHERE sid= eNO;
						    DBMS_OUTPUT.put_line('編號爲'||eNO||'僱員的姓名爲:'||stu.sname); --使用方法與表一致
						EXCEPTION
						    WHEN no_data_found THEN
						         DBMS_OUTPUT.put_line('沒有此僱員信息');	--對應情況下的信息顯示
						    WHEN ZERO_DIVIDE THEN
						         DBMS_OUTPUT.put_line('error');
						END;
			|-LOOP
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;  --給定初始值
						    LOOP
						        DBMS_OUTPUT.put_line(i);  --循環執行語句
						        EXIT WHEN i>= 10;
						        i:= i+ 1; --條件變更語句
						    END LOOP;
						END;
			|-WHILE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;  --給定初始值
						    WHILE(i<= 10) LOOP
						        DBMS_OUTPUT.put_line(i);
						        i:= i+ 1;
						    END LOOP;
						END;
			|-FOR
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    FOR i IN 1..10 LOOP
						        DBMS_OUTPUT.put_line(i);
						    END LOOP;
						END;
			|-IF
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 1;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    END IF;
						END;
			|-IF ESLE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    ELSE
						       DBMS_OUTPUT.put_line(i||'>= 10');
						    END IF;
						END;
			|-IF ESLIF ELSE
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       DBMS_OUTPUT.put_line(i||'< 10');
						    ELSIF i> 20 THEN
						       DBMS_OUTPUT.put_line(i||'> 20');
						    ELSE
						       DBMS_OUTPUT.put_line('10< '||i||'< 20');
						    END IF;
						END;
			|-GOTO
					|-DECLARE 
						    i NUMBER;
						BEGIN
						    i:= 11;
						    IF i< 10 THEN
						       GOTO to1;
						    ELSIF i> 20 THEN
						       GOTO to2;
						    ELSE
						       GOTO to3;
						    END IF;
						    <<to1>>
						        DBMS_OUTPUT.put_line(i||'< 10');
						    <<to2>>
						        DBMS_OUTPUT.put_line(i||'> 20');
						    <<to3>>
						        DBMS_OUTPUT.put_line('10< '||i||'< 20');
						END;
			
			
	|-遊標、函數
			|-遊標
					|-實質
							|-PL/SQL控制結構,便於對錶的行數據逐條進行處理,但它並非數據庫對象,只存留在內存中
					|-操作步驟
							|-聲明遊標
							|-打開遊標
							|-取出結果,注結果取出的爲一行數據
							|-關閉遊標
					|-例子
							|-FOR循環操作遊標,遊標只作爲結果集
									|-DECLARE
										CURSOR tmpCur IS SELECT * FROM student WHERE ssex= '男';
										stu student%ROWTYPE;
										sID NUMBER;
										BEGIN
										FOR stu IN tmpCur LOOP
										    sID:= tmpCur%ROWCOUNT;
										    DBMS_OUTPUT.put_line(sID||'ID= '||stu.sID||' ,sName= '||stu.sName);
										END LOOP;
										END;
							|-遍歷遊標,進行數據處理
									|-DECLARE
										CURSOR tmpCur IS SELECT * FROM student WHERE ssex= '男';  --進行遊標聲明
										stu student%ROWTYPE;
										sID NUMBER;
										BEGIN
										    IF tmpCur%ISOPEN THEN --打開遊標前先進行確認遊標是否已經打開
										       NULL;
										    ELSE
										       OPEN tmpCur;
										    END IF;
										    
										    FETCH tmpCur INTO stu;     --遊標數據封裝至變量中
										    WHILE(tmpCur%FOUND) LOOP   --判斷該行是否有數據
										        DBMS_OUTPUT.put_line('ID= '||stu.sID||' ,sName= '||stu.sName);
										        FETCH tmpCur INTO stu;
										    END LOOP;
										END;
			|-函數
					|-創建
							|-CREATE OR REPLACE FUNCTION test(sIn student.sID%TYPE)
								RETURN  student.sName%TYPE
								AS
								    sOut student.sName%TYPE;
								BEGIN
								    SELECT s.sname INTO sOut FROM student s WHERE s.sID= sIn;
								    RETURN sOut;
								END;
					|-使用
							|-SELECT test(80308078) FROM dual;




	|-存儲過程
			|-創建存儲過程
					|-CREATE OR REPLACE PROCEDURE pro(
				       sNO IN student.sid%TYPE, --IN表示只錄入
				       sXM OUT student.sname%TYPE --OUT表示只作爲數據輸出之用
						)
						AS
						BEGIN
						    SELECT sName INTO sXM FROM student WHERE sid= sNO;
						END;
			|-執行
					|-DECLARE
						  sXM student.sName%TYPE;
						BEGIN
						  pro(80308078, sXM);
						  DBMS_OUTPUT.put_line(sXM);
						END;
			|-刪除存儲過程
					|-DROP PROCEDURE pro;




	|-觸發器
			|-實質
					|-存放數據庫,並被隱含執行的存儲過程。
			|-創建(語句& 行觸發器)
					|-CREATE OR REPLACE TRIGGER tr_student_dml
						BEFORE INSERT OR UPDATE OR DELETE
						ON student
						BEGIN IF to_char(SYSDATE, 'dy') IN ('星期六', '星期天') THEN
						    CASE
						        WHEN inserting THEN
						            raise_application_error(-20001, '對不起,不能在指定日期插入檔案信息'); --用於返回自定義錯誤信息,數值支持-20000~-20999
						        WHEN updating THEN
						            raise_application_error(-20001, '對不起,不能在指定日期更新檔案信息');
						        WHEN deleting THEN
						            raise_application_error(-20001, '對不起,不能在指定日期刪除檔案信息');
						    END CASE;
						END IF;
						END;
						
						--建立關於student表的增、刪、改次記錄
						CREATE TABLE count_table(
						    cName VARCHAR2(30) NOT NULL,
						    bAdd NUMBER(1) DEFAULT 0,
						    bDelete NUMBER(1) DEFAULT 0,
						    bUpdate NUMBER(1) DEFAULT 0,
						    dChangeDate DATE  DEFAULT SYSDATE
						);


						CREATE OR REPLACE TRIGGER tr_count_student
						AFTER INSERT OR UPDATE OR DELETE
						ON student
						FOR EACH ROW --針對一語句影響多條的情況,針對每條進行處理	--行觸發,不加則行語句觸發
						BEGIN    --基於對student表的觸發,則代碼不能從觸發器所對應的基表中讀取數據
						    CASE 
						        WHEN inserting THEN
						            INSERT INTO count_table VALUES(upper('student'), 1, 0, 0, SYSDATE);
						            DBMS_OUTPUT.PUT_LINE(:new.sName);    --:new表示當前記錄,:old表示還舊記錄
						        WHEN updating THEN
						            INSERT INTO count_table VALUES(upper('student'), 0, 1, 0, SYSDATE);
						        WHEN deleting THEN
						            INSERT INTO count_table VALUES(upper('student'), 0, 0, 1, SYSDATE);
						    END CASE;
						END;
			|-測試
					|-DECLARE
						    no_babies_allowed EXCEPTION;
						    PRAGMA EXCEPTION_INIT(no_babies_allowed, -20001);     --預編譯將名稱與用於觸發器中的錯誤號碼關聯起來
						BEGIN
						    INSERT INTO student VALUES (1, 'yao', '男', 1, '');
						EXCEPTION
						    WHEN no_babies_allowed THEN    --SQLERRM 將傳遞給內置過程 RAISE_APPLICATION_ERROR 的消息返回
						        DBMS_OUTPUT.PUT_LINE(SQLERRM);       --返回指定代碼錯誤
						END;
			|-作用
					|-控制數據安全:在非工作時間不能對錶進行操作
					|-實現數據統計
					|-實現數據的完整性,進行數據的限制
					|-實現參照完整性:比如級聯更新
			|-系統事件觸發器
					|-基於Oracle系統事件(LOGON/STARTUP)所建立的觸發器,提供跟蹤系統或數據庫變化的機制。
					|-常用事件屬性函數
							|-ora_client_ip_address:返回客戶端IP地址
							|-ora_database_name:返回當前數據庫名
							|-ora_des_encrypted_password:返回DEX加密後的用戶口令
							|-ora_dict_obj_name:返回DDL操作中所對應的數據庫對象名
							|-ora_dict_obj_name_list(name_list OUT, ora_name_list_t):事件中被修改的對象名列表
							|-ora_dict_obj_type:返回DDL操作所對應的數據庫對象類型
							|-ora_grantee(user_list OUT ora_name_list_t):返回授權事件的授權者
							|-ora_instance_num:返回例程號
							|-ora_is_alter_column(column_name IN VARCHAR2):檢測特定列是否被修改
							|-ora_is_creating_nested_table:檢測是否正在建立嵌套表
							|-ora_is_drop_column(column_name IN VARCHAR2):檢測特定列是否被刪除
							|-ora_is_servererror(error_number):檢測是否返回特定Oracle錯誤
							|-ora_login_user:登陸用戶名
							|-ora_sysevent:返回觸發觸發器的系統事件名
					|-常用系統觸發
							|-開戶關閉數據庫時進行記錄
										CREATE TABLE sysevent_recored(
										    event VARCHAR2(100),
										    TIME DATE
										);
		
										CREATE OR REPLACE TRIGGER tr_startup
										AFTER startup
										ON DATABASE
										BEGIN
										    INSERT INTO sysevent_recored VALUES(ora_sysevent, SYSDATE);
										END;
										CREATE OR REPLACE TRIGGER tr_shutdown
										BEFORE SHUTDOWN
										ON DATABASE
										BEGIN
										    INSERT INTO sysevent_recored VALUES(ora_sysevent, SYSDATE);
										END;
							|-進行用戶登陸退出觸發
										CREATE TABLE log_record(
										    username VARCHAR2(30),
										    logon_time DATE,
										    logoff_time DATE,
										    address VARCHAR2(100)
										);
										
										CREATE OR REPLACE TRIGGER tr_logon
										AFTER logon
										ON DATABASE
										BEGIN
										    INSERT INTO log_record VALUES(username, logon_time, address) VALUES( ora_login_user, SYSDATE, ora_client_ip_address);
										END;
										CREATE OR REPLACE TRIGGER tr_logoff
										BEFORE logoff
										ON DATABASE
										BEGIN
										    INSERT INTO log_record VALUES(username, logoff_time, address) VALUES( ora_login_user, SYSDATE, ora_client_ip_address);
										END;
					|-觸發器管理
							|-顯示觸發器信息
									|-SELECT status, ut.* FROM User_Triggers ut;
							|-禁止
									|-ALTER TRIGGER TR_LOGOFF DISABLE;
									|-針對某表的所有觸發器生效:ALTER TABLE student DISABLE ALL TRIGGERS;
							|-激活
									|-ALTER TRIGGER TR_LOGOFF ENABLE;
									|-ALTER TABLE student ENABLE ALL TRIGGERS;
							|-重新編譯
									|-針對表結構發生變化後,觸發器進行INVALID狀態,需重新編譯進行觸發:ALTER TRIGGER TR_STUDENT_DML COMPILE;
							|-刪除
									|-DROP TRIGGER TR_STUDENT_DML;






	|-事務控制
			|-實質
					|-在Oracle的每個連接中都會產生一個Session,一個Session對數據庫的修改,不會立刻反應到數據庫的真實數據上,是允許回滾的。只有當提交了,纔會變成持久數據。
			|-原子性
					|-一個事務中,包含的若干個操作是一個整體需一起完成實現。
			|-一致性
					|-事務未提交前,修改用戶和其它用戶所見一致,其中其它用戶所見一致。
			|-隔離性
					|-未完成的事務不可見
			|-持久性
					|-事務提交後數據更新爲持久數據






	|-用戶管理
			|-創建用戶
					|-CREATE USER test IDENTIFIED BY test;
			|-刪除用戶
					|-
			|-創建Session權限
					|-分配連接權限,但還不能進行任何操作:GRANT CREATE SESSION TO test;
			|-用戶角色
					|-GRANT 
							CONNECT, --連接
					      	RESOURCE, --基本的業務表等的創建
					      	UNLIMITED TABLESPACE, --表空間操作
					     	 --DBA, --所有數據庫權限集合,不建議
					      	SELECT_CATALOG_ROLE,  --查詢數據字典視圖和包
					     	 EXP_FULL_DATABASE,
					      	IMP_FULL_DATABASE     --數據導入導出工具的使用
						TO test;
			|-鎖定用戶
					|-ALTER USER test ACCOUNT LOCK   --UNLOCK
			|-密碼失效
					|-密碼失效,會提示輸入新密碼:ALTER USER test PASSWORD EXPIRE;
			|-對象授權
					|-GRANT SELECT ON yqj.student TO test;
					|-GRANT ALL ON yqj.student TO test; --提供表的所有權限
					|-GRANT UPDATE(sid) ON yqj.student TO test; --控制到列權限
			|-權限回收
					|-注意只能回收表層次的權限,如對列的控制無法回收:REVOKE ALL ON yqj.student FROM test;
			|-查看權限
					|-查看當前用戶權限信息:SELECT * FROM user_sys_privs;
			|-權限傳遞
					|-權限sys->test->next,而移除test權限後,不影響next的權限:GRANT CREATE SESSION TO test WITH ADMIN OPTION;
			|-角色
					|-CREATE ROLE testRole;
					|-GRANT CREATE TABLE TO testRole;
					|-DROP ROLE testRole;
			|-完整流程
					|-
							--創建表空間
							CREATE TABLESPACE test
							DATAFILE 'D:\oracle\product\10.2.0\oradata\orcl\test.ora'
							SIZE 200M
							AUTOEXTEND ON NEXT 50M
							EXTENT MANAGEMENT LOCAL
							SEGMENT SPACE MANAGEMENT AUTO;
							
							CREATE TEMPORARY TABLESPACE test_temp
							TEMPFILE 'D:\oracle\product\10.2.0\oradata\orcl\test_temp.dbf'
							SIZE 50M
							AUTOEXTEND ON NEXT 50M
							EXTENT MANAGEMENT LOCAL;
							
							--增加相關用戶及權限
							CREATE USER test IDENTIFIED BY test
							DEFAULT TABLESPACE test
							TEMPORARY TABLESPACE test_temp;
							
							--增加相關用戶權限
							GRANT ALL PRIVILEGES TO test;
							
							--測試連接
							SELECT * FROM user_sys_privs;
			
			
			
			|-備份 恢復 SQLLDR
					|-IMP/EXP
							|-
								--完全導出/導入,導出整個數據庫
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE= D:\FULL.DMP FULL= Y;
								--導出/導入指定用戶信息
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE= D:\YQJ.DMP OWNER= YQJ;
								--導出/導入指定用戶信息下的指定表
								EXP/IMP YQJ/YQJ BUFFER=64000 FILE=D:\YQJ_STUDENT.DMP TABLES=(STUDENT); --OWNER=orcl 
					|-SQLLDR
							|-整理數據至CSV
									|-   	NAME	AGE	ADDRESS		CARDNO
												1			23	福建省			350582198903164000
												2			24	福建省			350582198903164001
												3			25	福建省			350582198903164002
												4			26	福建省			350582198903164003
							|-創建對應表
									|-CREATE TABLE sqlloader(
										NAME VARCHAR2(100) NOT NULL,
										age NUMBER(3) CHECK(age<300 AND age> 18),
										address VARCHAR2(300),
										cardNo VARCHAR2(50) UNIQUE NOT NULL
										);
							|-創建控制文件sqlloader.ctl
									|-load DATA           --控制文件標識
										infile 'd:\sqlloader.csv'   --輸入的數據文件名
										append INTO TABLE sqlloader    --向表追加記錄
										       --insert爲缺省方式,要求表爲空
										       --replace/truncate,刪除舊記錄並替換
										fields terminated BY ","
										optionally enclosed BY '"'
										(NAME, age, address, cardNo)--對應表單的字段名稱
							|-CMD執行調用語句
									|-sqlldr userid=yqj/yqj control= d:\sqlloader.ctl




	|-數據庫設計範式
			|-字段設計爲不可再分
			|-兩張表的關係,在第三張表中體現
			|-多張表中,只存關係,不存具體信息
			|-表關聯越少越好,SQL語句複雜度越低越好
			
			
			
			
			
	|-Oracle跨庫查詢
		|-建立DBlink 
			|-情況一:
					|-本地tnsnames.ora已配置如下
						|-bylw =
						  (DESCRIPTION =
						  (ADDRESS_LIST =
						  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))
						  )
						  (CONNECT_DATA =
						  (SERVER = DEDICATED)
						  (SERVICE_NAME = bylw)
						  )
						  )
					|-登陸創建鏈接
						|-create public database link
  						to_bylw connect to scott identified by tiger using 'bylw';
			|-情況二:
					|-本地tnsnames.ora中未配置
							|-	create database link to_test
							  connect to scott identified by tiger
							  using '(DESCRIPTION =
							  (ADDRESS_LIST =
							  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))
							  )
							  (CONNECT_DATA =
							  (SERVER = DEDICATED)
							  (SERVICE_NAME = bylw)
							  )
							  )';
							
		|-使用方式如下
			|-select * from scott.tb_test@to_bylw;

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