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;