課程 一 PL/SQL 基本查詢與排序css
本課重點:
一、寫SELECT語句進行數據庫查詢
二、進行數學運算
三、處理空值
四、使用別名ALIASES
五、鏈接列
六、在SQL PLUS中編輯緩衝,修改SQL SCRIPTS
七、ORDER BY進行排序輸出。
八、使用WHERE 字段。程序員
1、寫SQL 命令:
不區分大小寫。
SQL 語句用數字分行,在SQL PLUS中被稱爲緩衝區。
最後以;或 / 結束語句。
也能夠用RUN來執行語句sql
2、例1:
SQL> SELECT dept_id, last_name, manager_id
2 FROM s_emp;數據庫
SQL> SELECT last_name, salary * 12, commission_pct
2 FROM s_emp;express
對於數值或日期型的字段,能夠進行相應的四則運算,優先級與標準的高級語言相同。安全
SQL> SELECT last_name, salary, 12 * (salary + 100)
2 FROM s_emp;ide
3、列的別名ALIASES:
計算的時候特別有用;
緊跟着列名,或在列名與別名之間加「AS」;
若是別名中含有SPACE,特殊字符,或大小寫,要用雙引號引發。
例(因字體緣由,讀者請記住:引號爲英文雙引號Double Quotation):函數
SQL> SELECT last_name, salary,
2 12 * (salary + 100) 」Annual Salary」
3 FROM s_emp;oop
4、鏈接符號:||
鏈接不一樣的列或鏈接字符串
使結果成爲一個有意義的短語:
SQL> SELECT first_name || ’ ’ || last_name
2 || ’, ’|| title 」Employees」
3 FROM s_emp;性能
5、管理NULL值:
SQL> SELECT last_name, title,
2 salary * NVL(commission_pct,0)/100 COMM
3 FROM s_emp;
此函數使NULL轉化爲有意義的一個值,至關於替換NULL。
6、SQL PLUS的基本內容,請參考<SQL PLUS 簡單實用精髓篇 >
7、ORDER BY 操做:
與其餘SQL92標準數據庫類似,排序如:SELECT expr FROM table [ORDER BY [ASC|DESC]];
從Oracle7 release 7.0.16開始,ORDER BY 能夠用別名。
另:經過位置判斷排序:
SQL> SELECT last_name, salary*12
2 FROM s_emp
3 ORDER BY 2;
這樣就避免了再寫一次很長的表達式。
另:多列排序:
SQL> SELECT last name, dept_id, salary
2 FROM s_emp
3 ORDER BY dept_id, salary DESC;
8、限制選取行:
SELECT expr FROM table [WHERE condition(s)] [ORDER BY expr];
例1:
SQL> SELECT first_name, last_name, start_date
2 FROM s_emp
3 WHERE start_date BETWEEN ’09-may-91’
4 AND ’17-jun-91’;
例2:
SQL> SELECT last_name
2 FROM s_emp
3 WHERE last_name LIKE ’_a%’; //顯示全部第二個字母爲 a的last_name
例3:若是有列爲NULL
SQL> SELECT id, name, credit_rating
2 FROM s_customer
3 WHERE sales_rep_id IS NULL;
優先級:
Order Evaluated Operator
1 All comparison operators (=, <>, >, >=, <, <=, IN, LIKE, IS NULL, BETWEEN)
2 AND
3 OR
總結:咱們今天主要學習瞭如何進行查詢SELECT操做,具體的組合查詢與子查詢將在之後的課堂中學習,同時但願你們能夠工做、學習中多多摸索,實踐!
課程 二 PL/SQL 查詢行函數
本課重點:
一、掌握各類在PL/SQL中可用的ROW函數
二、使用這些函數的基本概念
三、SELECT語句中使用函數
四、使用轉換函數
1、FUNCTION的做用:
進行數據計算,修改獨立的數據,處理一組記錄的輸出,不一樣日期顯示格式,進行數據類型轉換
函數分爲:單獨函數(ROW)和分組函數
注意:能夠嵌套、能夠在SELECT, WHERE, 和 ORDER BY中出現。
語法:function_name (column|expression, [arg1, arg2,...])
2、字符型函數
一、LOWER 轉小寫
二、UPPER
三、INITCAP 首字母大寫
四、CONCAT 鏈接字符,至關於 ||
五、SUBSTR SUBSTR(column|expression,m[,n])
六、LENGTH 返回字符串的長度
七、NVL 轉換空值
其中,一、2常常用來排雜,也就是排除插入值的大小寫混用的干擾,如:
SQL> SELECT first_name, last_name
2 FROM s_emp
3 WHERE UPPER(last_name) = ’PATEL’;
FIRST_NAME LAST_NAME
-------------------- --------------------
Vikram Patel
Radha Patel
3、數學運算函數
一、ROUND 四捨五入
ROUND(45.923,2) = 45.92
ROUND(45.923,0) = 46
ROUND(45.923,-1) = 50
二、TRUNC 截取函數
TRUNC(45.923,2)= 45.92
TRUNC(45.923)= 45
TRUNC(45.923,-1)= 40
三、MOD 餘除
MOD(1600,300)
實例:
SQL> SELECT ROUND(45.923,2), ROUND(45.923,0),
2 ROUND(45.923,-1)
3 FROM SYS.DUAL;
4、ORACLE 日期格式和日期型函數:
一、默認格式爲DD-MON-YY.
二、SYSDATE是一個求系統時間的函數
三、DUAL['dju:el] 是一個僞表,有人稱之爲空表,但不確切。
SQL> SELECT SYSDATE
2 FROM SYS.DUAL;
四、日期中應用的算術運算符
例:
SQL> SELECT last_name, (SYSDATE-start_date)/7 WEEKS
2 FROM s_emp
3 WHERE dept_id = 43;
DATE+ NUMBER = DATE
DATE-DATE= NUMBER OF DAYS
DATE + (NUMBER/24) = 加1小時
五、函數:
MONTHS_BETWEEN(date1, date2) 月份間隔,可正,可負,也但是小數
ADD_MONTHS(date,n) 加上N個月,這是一個整數,但能夠爲負
NEXT_DAY(date,‘char’) 如:NEXT_DAY (restock_date,’FRIDAY’),今後日起下個週五。
ROUND(date[,‘fmt’])
TRUNC(date[,‘fmt’])
解釋下面的例子:
SQL> SELECT id, start_date,
2 MONTHS_BETWEEN (SYSDATE,start_date) TENURE,
3 ADD_MONTHS(start_date,6) REVIEW
4 FROM s_emp
5 WHERE MONTHS_BETWEEN (SYSDATE,start_date)<48;
咱們看到:
MONTHS_BETWEEN (SYSDATE,start_date)<48,說明至今工做未滿一年的員工。
LAST_DAY (restock_date) 返回本月的最後一天
SQL> select round(sysdate,'MONTH') from dual
ROUND(SYSD
----------
01-11月-01
round(sysdate,'YEAR') = 01-1月 -02
ROUND 以後的值比基值大的最小符合值,你們能夠用更改系統時間的方法測試,以15天爲分界線,也是很是形象的四捨五入,而TRUNC剛好相反,是對現有的日期的截取。
5、轉換函數:
一、TO_CHAR 使一個數字或日期轉換爲CHAR
二、TO_NUMBER 把字符轉換爲NUMBER
三、TO_DATE 字符轉換爲日期
這幾個函數較爲簡單,但要多多實踐,多看複雜的實例。
SQL> SELECT ID,TO_CHAR(date_ordered,’MM/YY’) ORDERED
2 FROM s_ord
3 WHERE sales_rep_id = 11;
轉換時,要注意正確的缺省格式:
SELECT TO_DATE('03-MAR-92') CORRECT FROM DUAL;//正確
SELECT TO_DATE('031092') CORRECT FROM DUAL;//不正確
SELECT TO_DATE('031095','MMDDYY') ERRORR FROM DUAL // 輸出 3月10日
SELECT TO_DATE('031095','DDMMYY') ERRORR FROM DUAL // 輸出 10月3日
四、實例:
select to_char(sysdate,'fmDDSPTH "of" MONTH YYYY AM') TODAYS FROM DUAL;
TODAYS
--------------------------------
SIXTEENTH of 11月 2001 下午
大小寫沒有什麼影響,引號中間的是不參與運算。
實例 :
SELECT ROUND(SALARY*1.25) FROM ONE_TABLE;
意義:漲25%工資後,去除小數位。在現實操做中,頗有意義。
五、混合實例:
SQL> SELECT last_name, TO_CHAR(start_date,
2 ’fmDD 」of」 Month YYYY’) HIREDATE
3 FROM s_emp
4 WHERE start_date LIKE ’%91’;
LAST_NAME HIREDATE
------------ --------------------
Nagayama 17 of June 1991
Urguhart 18 of January 1991
Havel 27 of February 1991
這裏要注意:fmDD 和 fmDDSPTH之間的區別。
SQL> SELECT id, total, date_ordered
2 FROM s_ord
3 WHERE date_ordered =
4 TO_DATE(’September 7, 1992’,’Month dd, YYYY’);
6、獨立的函數嵌套
SQL> SELECT CONCAT(UPPER(last_name),
2 SUBSTR(title,3)) 」Vice Presidents」
3 FROM s_emp
4 WHERE title LIKE ’VP%’;
* 嵌套能夠進行到任意深度,從內向外計算。
例:
SQL> SELECT TO_CHAR(NEXT_DAY(ADD_MONTHS
2 (date_ordered,6),’FRIDAY’),
3 ’fmDay, Month ddth, YYYY’)
4 」New 6 Month Review」
5 FROM s_ord
6 ORDER BY date_ordered;
SQL> SELECT last_name,
2 NVL(TO_CHAR(manager_id),’No Manager’)
3 FROM s_emp
4 WHERE manager_id IS NULL;
對於例子,你們重要的理解,並多作測試,並注意英文版和中文版在日期上的區別。
有些教材上的例子,不要盲目的相信其結果,實踐後纔有發言權,但願你們可以在學習的過程當中不要忽略了用,多想想爲何實例要如此設計,在何種狀況下應用此實例來解決問題。這樣,咱們才真正掌握了知識。
課程 三 從多個表中提取數據
本課重點:
一、SELECT FROM 多個表,使用等鏈接或非等鏈接
二、使用外鏈接OUTER JOIN
三、使用自鏈接
1、鏈接的概念:
是指一個從多個表中的數據進行的查詢。鏈接通常使用表的主鍵和外鍵。
鏈接類型:等鏈接、不等鏈接、外鏈接、自鏈接
2、Cartesian product(笛卡兒集)
指的是當JOIN條件被省略或無效時,全部表的行(交叉)都被SELECT出來的現象。
Cartesian product能夠產生大量的記錄,除非是你有意如此,不然應該加上某種條件限制。
SQL> SELECT name, last_name
2 FROM s_dept, s_emp;
300 rows selected.
其中一個表12行,一個表25行。
3、簡單鏈接查詢:
語法結構:SELECT table.column, table.column...
FROM table1, table2
WHERE table1.column1 = table2.column2;
如:
SQL> SELECT s_emp.last_name, s_emp.dept_id,
2 s_dept.name
3 FROM s_emp, s_dept
4 WHERE s_emp.dept_id = s_dept.id;
*注意:表前綴的重要性:
SQL> SELECT s_dept.id 」Department ID」,
2 s_region.id 」Region ID」,
3 s_region.name 」Region Name」
4 FROM s_dept, s_region
5 WHERE s_dept.region_id = s_region.id;
在WHERE 段中,若是沒有前綴,兩個表中都有ID字段,就顯得的模棱兩可,AMBIGUOUS。
這在實際中應該儘可能避免。
WHERE 字段中,還能夠有其餘的鏈接條件,如在上例中,加上:
INITCAP(s_dept.last_name) = ’Menchu’;
再如:WHERE s_emp.dept_id = s_dept.id AND s_dept.region_id = s_region.id AND s_emp.commission_pct > 0;
4、表別名ALIAS:
一、使用別名進行多表查詢 。
二、僅在這個查詢中生效,一旦用了表別名,就不能再用表的原有的名字進行鏈接。
實例:
SQL> SELECT c.name 」Customer Name」,
2 c.region_id 」Region ID」,
3 r.name 」Region Name」
4 FROM s_customer c, s_region r
5 WHERE c.region_id = r.id;
別名最多能夠30個字符,但固然越少越好。最好也能容易識別。
5、非等鏈接
非等鏈接通常用在沒有明確的等量關係的兩個表;
最簡單的說:非等鏈接就是在鏈接中沒有「=」出現的鏈接。
SQL> SELECT e.ename, e.job, e.sal, s.grade
2 FROM emp e, salgrade s
3 WHERE e.sal BETWEEN s.losal AND s.hisal;
*說明:Create a non-equijoin to evaluate an employee’s salary grade. The salary 必須在另外一個表中最高和最低之間。
其餘操做符<= >= 也能夠實現,可是BETWEEN是很是簡單實用的。
BETWEEN ....AND是指閉區間的,這點要注意 ,請你們測試。
6、外鏈接
語法結構:SELECT table.column, table.column
FROM table1, table2
WHERE table1.column = table2.column(+);
實例:
SQL> SELECT e.last_name, e.id, c.name
2 FROM s_emp e, s_customer c
3 WHERE e.id (+) = c.sales_rep_id
4 ORDER BY e.id;
顯示.....,即便有的客戶沒有銷售表明。
* 能夠理解爲有+號的一邊出現了NULL,也能夠作爲合法的條件。
外鏈接的限制:
一、外鏈接符只能出如今信息缺乏的那邊。
二、在條件中,不能用 IN 或者 OR作鏈接符。
7、自鏈接
同一個表中使用鏈接符進行查詢;
FROM 的後面用同一個表的兩個別名。
實例:
SQL> SELECT worker.last_name||’ works for ’||
2 manager.last_name
3 FROM s_emp worker, s_emp manager
4 WHERE worker.manager_id = manager.id;
意味着:一個員工的經理ID匹配了經理的員工號,但這個像繞口令的鏈接方式並不經常使用。
之後咱們會見到一種 子查詢:
select last_name from s_emp where salary=(select max(salary) from s_emp)
也能夠看做是一種變向的自鏈接,但一般咱們將其歸類爲子查詢。
課程 四 組函數
本課重點:
一、瞭解可用的組函數
二、說明每一個組函數的使用方法
三、使用GROUP BY
四、經過HAVING來限制返回組
1、概念:
組函數是指按每組返回結果的函數。
組函數能夠出如今SELECT和HAVING 字段中。
GROUP BY把SELECT 的結果集分紅幾個小組。
HAVING 來限制返回組,對RESULT SET而言。
2、組函數:(#號的函數不作重點)
一、AVG
二、COUNT
三、MAX
四、MIN
五、STDDEV #
六、SUM
七、VARIANCE #
語法:
SELECT column, group_function
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING group_condition]
[ORDER BY column];
實例1:
SQL> SELECT AVG(salary), MAX(salary), MIN(salary),
2 SUM(salary)
3 FROM s_emp
4 WHERE UPPER(title) LIKE ’SALES%’;
AVG(SALARY) MAX(SALARY) MIN(SALARY) SUM(SALARY)
----------- ----------- ----------- -----------
1476 1525 1400 7380
*說明:不少函數,咱們在講函數的已經向你們介紹過,但在此爲什麼叫分組函數呢,主要是由於它們能夠與GROUP BY來造成對不一樣組的計算,至關於在不少值中進行挑選。
* MIN MAX函數能夠接任何數據類型。
若是是MIN(last_name), MAX(last_name),返回的是什麼呢?
千萬記住,不是指LAST_NAME的長度,而是指在FIRST字母的先後順序,第一個相同,而後比較第二個,如:xdopt > cssingkdkdk > adopt > acccc
實例2:(返回全部非空行個數)
SQL> SELECT COUNT(commission_pct)
2 FROM s_emp
3 WHERE dept_id = 31;
3、GROUP BY的應用:
先看一個簡單實例:
SQL> SELECT credit_rating, COUNT(*) 」# Cust」
2 FROM s_customer
3 GROUP BY credit_rating;
*注意這裏別名的應用,複習一下從前的課程,加了引號後,就能夠用特殊字符,但也僅有三個:#$_,什麼對象的名字都如此。固然空格也是能夠的。
複雜實例:
SQL> SELECT title, SUM(salary) PAYROLL
2 FROM s_emp
3 WHERE title NOT LIKE ’VP%’
4 GROUP BY title
5 ORDER BY SUM(salary);
這裏要注意一下幾個CLAUSE的前後次序。WHERE在這裏主要是作參與分組的記錄的限制。
**另外,若是要選取出來一個不加組函數的列,如上面的TITLE,就要把這個列GROUP BY !不然要出錯的!信息爲:
ERROR at line 1:
ORA-00937: not a single-group group function
理論很簡單,若是不GROUP BY TITLE,顯示哪個呢?這個在試題中常常出現。
結論:不加分組函數修飾的列一定要出如今GROUP BY 裏。
錯誤實例:
SQL> SELECT dept_id, AVG(salary)
2 FROM s_emp
3 WHERE AVG(salary) > 2000
4 GROUP BY dept_id;
5 WHERE AVG(salary) > 2000
ERROR at line 3:
ORA-00934: group function is not allowed here
應在GROUP BY 後面加上HAVING AVG(salary) > 2000;由於是用來限制組的返回。
多級分組實例:
SQL> SELECT dept_id, title, COUNT(*)
2 FROM s_emp
3 GROUP BY dept_id, title;
就是先按照DEPT_ID分組,當DEPT_ID相同的時候,再按TITLE分組,而COUNT(*)以合成的組計數。順序對結果有決定性的影響。
總結:本課咱們主要學習了分組函數的使用及如何進行分組查詢,咱們能夠想像一下,SQL SERVER中有COMPUTE BY,來進行分組總數的計算,但在ORACLE中是沒有的。你們能夠創建一個有多個列,多個重複值的表,而後進行各類分組的演示,用得多了,天然明瞭。
課程 五 子查詢
本課重點:
一、在條件未知的狀況下采用嵌套子查詢
二、用子查詢作數據處理
三、子查詢排序
1、概述:
子查詢是一種SELECT句式中的高級特性,就是一個SELECT語句做爲另外一個語句的一個段。咱們能夠利用子查詢來在WHERE字段中引用另外一個查詢來攻取值以補充其沒法事先預知的子結果。子查詢能夠用在WHERE子句,HAING子句,SELECT或DELETE語句中的FROM 子句。
*注意:
一、子查詢必須在一對圓括號裏。
二、比較符號:>, =, 或者 IN.
三、子查詢必須出如今操做符的右邊
四、子查詢不能出如今ORDER BY裏 (試題中有時出現找哪行出錯)
2、子查詢的執行過程:
NESTED QUERY MAIN QUERY
SQL> SELECT dept_id SQL> SELECT last_name, title
2 FROM s_emp 2 FROM s_emp
3 WHERE UPPER(last_name)=’BIRI’; 3 WHERE dept_id =
這裏 ,每一個查詢只運行一次。固然,子查詢要首先被執行,你們設想一下,若是子查詢中有一個以上的人的LASTNAME爲BIRI,會如何?-----會出錯,由於不能用=來鏈接。
ORA-1427: single-row subquery returns more than one row
以上的查詢也被稱之爲單行子查詢。
DELECT子查詢實例:
delete from new_table
where cata_time > to_date('19990901','yyyymmdd') and pro_name=(
select pro_name from new_product where pro_addr in ('bj','sh'))
3、子查詢中的GROUP 函數的應用
實例 1:
SQL> SELECT last_name, title, salary
2 FROM s_emp
3 WHERE salary <
4 (SELECT AVG(salary)
5 FROM s_emp);
實例2:選擇出工資最高的員工的家庭住址:
select emp_addr from employees where salary =
(select max(salary) from employees);
這是一個簡單實用的例子,能夠衍生出不少狀況,在實際應用常常出現,請你們多多思考。
實例3:
SQL> SELECT dept_id, AVG(salary)
2 FROM s_emp
3 GROUP BY dept_id
4 HAVING AVG(salary) >
5 (SELECT AVG(salary)
6 FROM s_emp
7 WHERE dept_id = 32);
子查詢被屢次執行,由於它出如今HAVING 子句中。
SQL> SELECT title, AVG(salary)
2 FROM s_emp
3 GROUP BY title
4 HAVING AVG(salary) =
5 (SELECT MIN(AVG(salary))
6 FROM s_emp
7 GROUP BY title);
對子查詢,咱們瞭解這麼多在理論上已經覆蓋了全部的知識點,對於UPDATE 和DELETE的子查詢,不做爲重點,但也要練習掌握。今天到這,謝謝你們。
課程 六 運行時應用變量
本課重點:
一、建立一個SELECT語句,提示USER在運行時先對變量賦值。
二、自動定義一系列變量,在SELECT運行時進行提取。
三、在SQL PLUS中用ACCEPT定義變量
1、概述:
變量能夠在運行時應用,變量能夠出如今WHERE 字段,文本串,列名,表名等。
一、咱們這裏的運行時,指的是在SQL PLUS中運行。
二、ACCEPT :讀取用戶輸入的值並賦值給變量
三、DEFINE:建立並賦值給一個變量
四、在作REPORT時常用,好比對某個部門的銷售信息進行統計,部門名稱能夠以變量代替。
SQL PLUS不支持對輸入數據的有效性檢查,所以提示要簡單且不模棱兩可。
2、應用實例:
一、
SQL> SELECT id, last_name, salary
2 FROM s_emp
3 WHERE dept_id = &department_number;
二、能夠在賦值先後進行比較:
SET VERIFY ON
.....
1* select * from emp where lastname='&last_name'
輸入 last_name 的值: adopt
原值 1: select * from emp where lastname='&last_name'
新值 1: select * from emp where lastname='adopt'
----若是在原語句中沒有單引號,那麼在輸入值的時候要手工加上單引號。通常字符和日期型要在語句中加上單引號。
SET VERIFY OFF 以後,原值和新值這兩句消失。這在ORACLE8I中是默認爲ON。
三、子句爲變量:WHERE &condition; 要注意引號
3、DEFINE和ACCEPT的應用:
一、
SET ECHO OFF //使內容不 顯示在用戶界面
ACCEPT p_dname PROMPT ’Provide the department name: ’
SELECT d.name, r.id, r.name 」REGION NAME」
FROM s_dept d, s_region r
WHERE d.region_id = r.id AND UPPER(d.name) LIKE UPPER(’%&p_dname%’)
/
SET ECHO ON
存爲文件:l7prompt.SQL
SQL> START l7prompt
Provide the department name: sales
二、
SQL> DEFINE dname = sales
SQL> DEFINE dname
DEFINE dname = 」sales」 (CHAR)
SQL> SELECT name
2 FROM s_dept
3 WHERE lower(name) = ’&dname’;
能夠正常執行了。
SQL> DEFINE dname 主要是顯示當前的變量是否賦值,值是什麼。固然,咱們能夠用UNDEFINEGO 來使變量恢復初始,否則它會一直保持下去。
三、若是變量在SQL SCRIPT文件中肯定 :能夠SQL> START l7param President 來賦值。
總結:本課主要針對較古老的SQLPLUS方法,在REPORT和結果集生成方面使用變量,達到方便操做,動態修改的目的。
課程 七 其餘數據庫對象
SEQUENCE
建立實例:
SQL> CREATE SEQUENCE s_dept_id
2 INCREMENT BY 1
3 START WITH 51
4 MAXVALUE 9999999
5 NOCACHE
6 NOCYCLE;
Sequence created.
一、NEXTVAL和CURRVAL的用法
只有在INSERT中,才能夠做爲子查詢出現。
如下幾個方面不可用子查詢:
SELECT子句OF A VIEW
有DISTINCT的出現的SELECT。
有GROUP BY,HAVING,ORDER BY的SELECT 子句。
SELECT 或DELETE,UPDATE 中的子查詢。
DEFAULT選項中不能用。
二、編輯SEQUENCE
只有OWNER或有ALTER權限的用戶才能修改SEQUENCE
將來的NUMBER受修改的影響。
不能修改START WITH,若是變,則要RE-CREATE。
修改會受到某些有效性檢驗的限制,如MAXVALUE
三、刪除:
DROP SEQUENCE sequence;
ORACLE對象之INDEX
1、INDEX概述:
是ORACLE的一種數據對象,用POINTER來加速查詢行。經過快速路徑存取方法定位數據並減小I/O。 INDEX獨立於表。INDEX由ORACLE SERVER來使用和保持。
2、索引如何創建?
一、自動:經過PRIMARY KEY和UNIQUE KEY約束來創建。
二、用戶手工創建非惟一性索引。
3、建立方法:
語法:CREATE INDEX index ON table (column[, column]...);
什麼時候創建INDEX:
此列常常被放到WHERE字段或JOIN來做條件查詢。
此列含有大量的數據。
此列含有大量的空值。
兩個或幾個列常常同時放到WHERE字段進行組合查詢
表很大並且只有少於2-4% 的ROW可能被查詢的時候。
如下狀況不要創建索引:
表很小;
表被更新頻繁。
4、查看已經存在的索引:
一、USER_INDEXES能夠查詢索引名和類型。
二、USER_IND_COLUMNS包含索引名、表名、列名。
實例:
SQL> SELECT ic.index_name, ic.column_name,
2 ic.column_position col_pos, ix.uniqueness
3 FROM user_indexes ix, user_ind_columns ic
4 WHERE ic.index_name = ix.index_name
5 AND ic.table_name = ’S_EMP’;
5、刪除索引:
DROP INDEX index;
SYNONYMS 同義詞
語法:CREATE [PUBLIC] SYNONYM synonym for object;
*注意:此對象不能包含在一個包裏;一個私有的同義詞不能與同一USER的其餘對象重名。
DROP SYNONYM D_SUM;
課程 八 用戶訪問控制
本課重點:
一、建立用戶
二、建立角色來進行安全設置
三、使用GRANT或REVOKE 來控制權限
1、概述:
ORACLE經過用戶名和密碼進行權限控制。
數據庫安全:系統安全和數據安全
系統權限:使用戶能夠訪問數據庫
對象權限:操縱數據庫中的對象
SCHEMA:各類對象的集合
2、系統權限:
一、超過80個權限可用。
二、DBA有最高的系統權限:
CREATE NEW USER
REMOVE USERS
REMOVE ANY TABLE
BACKUP ANY TABLE
3、建立用戶
一、CREATE USER user IDENTIFIED BY password;
二、系統權限:
CREATE SESSION Connect to the database.
CREATE TABLE Create tables in the user’s schema.
CREATE SEQUENCE Create a sequence in the user’s schema.
CREATE VIEW Create a view in the user’s schema.
CREATE PROCEDURE Create a stored procedure, function, or package in the user’s schema.
三、受權用戶系統權限:
GRANT privilege [, privilege...] TO user [, user...];
GRANT CREATE TABLE TO SCOTT;
4、角色的使用
一、概念:角色是一組權限的命名,能夠授予給用戶。這樣就如同給了某個用戶一個權限包。
二、建立、授予給角色:
CREATE ROLE MANAGER;
GRANT CREATE TABLE,CREATE VIEW TO MANAGER;
GRANT MANAGER TO CLARK
5、修改密碼:
ALTER USER user IDENTIFIED BY password;
6、對象權限:
一、語句:
GRANT {object_priv(, object_priv...)|ALL}[(columns)]
ON object
TO {user[, user...]|role|PUBLIC}
[WITH GRANT OPTION];
二、實例:
最簡單:
SQL> GRANT select
2 ON s_emp
3 TO sue, rich;
稍複雜:
SQL> GRANT update (name, region_id)
2 ON s_dept
3 TO scott, manager;
SQL> GRANT select, insert
2 ON s_dept
3 TO scott
4 WITH GRANT OPTION;
課程 九 聲明變量
本課重點:
一、瞭解基本的PLSQL塊和區域
二、描述變量在PLSQL中的重要性
三、區別PLSQL與非PLSQL變量
四、聲明變量
五、執行PLSQL塊
1、概述:
一、PLSQL 塊結構:
DECLARE --- 可選 變量聲明定義
BEGIN ---- 必選 SQL 和PLSQL 語句
EXCEPTION ---- 可選 錯誤處理
END;---- 必選
2、實例:
declare
vjob varchar(9);
v_count number:=0;
vtotal date:=sysdate +7;
c_tax constant number(3,2):=8.25;
v_valid boolean not null:=true;
begin
select sysdate into vtotal from dual;
end;
/
上例中,若是沒有這個SELECT語句,會如何?
出錯,說明必須有STATEMENTS
若是: select sysdate from dual into vtotal ;
一樣,也不行。並且變量與賦值的類型要匹配。
3、%TYPE的屬性
聲明一個變量使之與數據庫某個列的定義相同或與另外一個已經定義過的變量相同,因此%TYPE要做爲列名的後綴:如:
v_last_name s_emp.last_name%TYPE;
v_first_name s_emp.first_name%TYPE; --這樣作的好處是咱們沒必要去知曉此列的類型與定義
或:
v_balance NUMBER(7,2);
v_minimum_balance v_balance%TYPE := 10;
4、聲明一個布爾類型的變量
1 只有TRUE、FALSE、NULL能夠賦值給BOOLEAN變量
2 此變量能夠接邏輯運算符NOT、AND、OR。
三、變量只能產生TRUE、FALSE、NULL。
實例:
VSAL1:=50000;
VSQL2:=60000;
VCOMMSAL BOOLEAN:=(VSAL1<VSQL2); --實際上是把TRUE賦值給此變量。
5、LOB 類型的變量
共有CLOB、BLOB、BFILE、NCLOB幾種,這裏不作爲重點。
六:使用HOST VARIABLES
SQL> variable n number
SQL> print n
:n=v_sal /12;
:n這個加了:前綴的變量不是PLSQL變量,而是HOST。
7、如下幾個PLSQL聲明變量,哪一個不合法?
A 、DECLARE
V_ID NUMBER(4);
B、DECLARE
V_X,V_Y,V_Z VARCHAR2(9);
C、DECLARE
V_BIRTH DATE NOT NULL;
D、DECLARE
V_IN_STOCK BOOLEAN:=1;
E、DECLARE
TYPE NAME_TAB IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;
DEPT_NAME NAME_TAB;
上面的習題我會在下章給出答案,這也正是聲明變量的規則和難點。
課程 十 寫執行語句
本課重點:
一、瞭解PLSQL執行區間的重要性
二、寫執行語句
三、描述嵌套塊的規則
四、執行且測試PLSQL塊
五、使用代碼慣例
1、PLSQL 塊的語法規則:
一、語句能夠跨躍幾行。
二、詞彙單元能夠包括:分隔符、標識符、文字、和註釋內容。
三、分隔符: +-*/=<>||....
四、標識符:
最多30個字符,不能有保留字除非用雙引號引發。
字母開頭,不與列同名。
五、文字串:如 V_ENAME:='FANCY';要用單引號括起來。
數值型能夠用簡單記數和科學記數法。
六、註釋內容:單行時用-- 多行用/* */
與C很類似
2、SQL函數在PL/SQL的使用:
一、可用的:單行數值型、字符型和轉換型,日期型。
二、不可用的:最大、最小、DECODE、分組函數。
實例:
BEGIN
SELECT TO_CHAR(HIREDATE,'MON,DD,YYYY') FROM EMP;
END;
V_comment:=user||':'||sysdate; -- 會編譯出錯
V_comment:=user||':'||to_char(sysdate); --正確
若是有可能,PLSQL都會進行數據一致性的轉換,但ORACLE推薦你應該進行顯示的轉換,由於這樣會提升性能。
3、嵌套塊和變量做用區域
一、執行語句容許嵌套時嵌套。
二、嵌套塊能夠看做正常的語句塊。
三、錯誤處理模塊能夠包括一個嵌套塊
四、exponential指數 邏輯、算數、鏈接、小括號
五、看正面實例:
declare
vjob varchar(9);
v_count number:=0;
vtotal date:=sysdate +7;
c_tax constant number(3,2):=8.25;
v_valid boolean not null:=true;
ttt vtotal%type;
begin
--select sysdate into vtotal from dual;--體會有無此句與結果的影響
dbms_output.put_line (vtotal);
end;
/
*注意:在執行塊以前,要在SQL PLUS中執行:SET SERVEROUTPUT ON
3、以實例來講明函數的參數聲明做用域
declare
v_weight number(3):=600;
v_message varchar2(255):='product10000';
begin
declare
--sub-block
v_weight number(3):=1;
v_message varchar2(255):='pro300';
begin
v_weight:=v_weight +1;
end;
v_weight:=v_weight +1;
v_message:=v_message || 'my name';
end;
/
子塊中的V_WEIGHT值爲 2
咱們能夠在子塊中加入:dbms_output.put_line('subblock value is '||v_weight);
在主體中加入:dbms_output.put_line('main value is '||v_weight);
咱們發現MAINBLOCK中V_WEIGHT爲 601
改動:
一、在主塊的聲明中加 v_date date default sysdate;
在子塊中加入:dbms_output.put_line('subblock date value is '||v_date);
執行結果:subblock date value is 22-11月-01
*說明:主塊中的變量,若是子塊中沒有同名變量聲明,則繼承主塊中的聲明和初始化值;
二、在子塊中加入:v_sub char(9);
dbms_output.put_line('subblock char value is '||v_sub);
此時正常輸出。
在主塊中加入:dbms_output.put_line('main char value is '||v_sub);
輸出:ORA-06550: 第 21 行, 第 45 列:
PLS-00201: 必須說明標識符 'V_SUB'
*說明:
子塊中聲明的變量主塊中並不知曉,所以出錯。瞭解了此實例,一切狀況的變量的值的走向就都明瞭了。
課程 十一 與ORACLE SERVER交互
本課重點:
一、在PLSQL中成功的寫SELECT語句
二、動態聲明PLSQL變量類型與SIZE
三、在PLSQL中寫DML語句
四、在PLSQL中控制事務
五、肯定DML操做的結果
1、PLSQL中的SQL語句:
SELECT、DML、COMMIT、ROLLBACK、SAVEPOINT、CURSOR
特殊強調:PLSQL不支持DCL,不要問爲何。(DBMS_SQL package allows you to issue DDL and DCL statements.)
2、SELECT
SELECT select_list INTO variable_name | record_name
FROM table WHERE condition;
例:
SQL> r
1 declare
2 v_deptno number(2);
3 v_loc varchar2(15);
4 begin
5 select deptno,loc
6 into v_deptno,v_loc
7 from dept
8 where dname='SALES';
9 DBMS_OUTPUT.PUT_LINE (V_deptno ||' and '||v_loc);
10* end;
30 and CHICAGO
選取字段與變量個數和類型要一致。聲明的變量必定要在SIZE上大於返回的賦值,不然提示緩衝區溢出。
若是SELECT語句沒有返回值:ORA-01403: 未找到數據
ORA-06512: 在line 5
若是有多個值返回:ORA-01422: 實際返回的行數超出請求的行數
這些咱們到了錯誤處理時會逐一講解。
例:
上面的例子能夠改成:
declare
v_deptno dept.deptno%type;
v_loc dept.loc%type;
begin
select deptno,loc
into v_deptno,v_loc
from dept
where dname='SALES';
DBMS_OUTPUT.PUT_LINE (V_deptno ||' and '||v_loc);
end;
/
這樣,能夠在未知其餘字段大小和類型的時候定義變量,提升兼容性。
3、DML 操做:
一、實例:
declare
v_empno emp.empno%type;
begin
select max(empno)
into v_empno
from emp;
v_empno:=v_empno+1;
insert into emp(empno,ename,job,deptno)
values(v_empno,'asdfasdf','ddddd',10);
end;
/
這樣也能夠實現如SEQUENCE同樣的編號惟一遞增。
二、更新和刪除:
這個較爲簡單:
DECLARE
V_DEPTNO EMP.DEPtno%type :=10;
begin
delete from emp where deptno=v_deptno;
end;
/
PLSQL首先檢查一個標識符是不是一個數據庫的列名,若是不是,再假定它是一個PLSQL的標識符。因此若是一個PLSQL的變量名爲ID,列中也有個ID,如:
SELECT date_ordered, date_shipped
INTO date_ordered, date_shipped
FROM s_ord
WHERE id = id;
就會返回TOO MANY ROWS,這是要儘可能避免的。
4、SQL CURSOR
遊標是一個獨立SQL工做區,有兩種性質的遊標:
隱式遊標: 當PARSE 和EXECUTE 時使用隱式遊標。
顯式遊標: 是由程序員顯式聲明的。
遊標的屬性:
SQL%ROWCOUNT:一個整數值,最近SQL語句影響的行數。
SQL%FOUND BOOLEAN屬性,若是爲TRUE,說明最近的SQL STATEMENT有返回值。
SQL%NOTFOUND 與SQL%FOUND相反
SQL%ISOPEN 在隱式遊標中常常是FALSE,由於執行後當即自動關閉了。
SQL> variable row_de number
SQL> r
1 declare
2 v_deptno number:=10;
3 begin
4 delete from emp where
5 deptno=v_deptno;
6 :row_de:=sql%rowcount;
7* end;
PL/SQL 過程已成功完成。
SQL> print row_de --這是一個SQL PLUS變量
ROW_DE
----------
4
這時其實並無真正的刪除,而是須要 COMMIT或ROLLBACK,來完成事務。
課程 十二 編寫控制結構語句
本課重點:
一、結構控制的的用途和類型
二、IF 結構
三、構造和標識不一樣的循環
四、使用邏輯表
五、控制流和嵌套
1、控制執行流
能夠是分支和循環:IF THEN END IF
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
例子:
IF V_ENAME='OSBORNE' THEN
V_MGR:=22;
END IF;
這裏咱們能夠注意,PLSQL和C語言或JAVA在條件上的不一樣,=表明關係運算,而:=表明賦值。
看一個函數:
create FUNCTION calc_val
(v_start IN NUMBER)
RETURN NUMBER
IS
BEGIN
IF v_start > 100 THEN
RETURN (2 * v_start);
ELSIF v_start >= 50 THEN
RETURN (.5 * v_start);
ELSE
RETURN (.1 * v_start);
END IF;
END calc_val;
如今,雖然咱們還沒有講解CREATE 函數或過程,但能夠看到IF 條件在其中的做用。
2、注意LOGIC TABLE中的邏輯對應關係
一、NOT、AND、OR
二、任何表達式中含有空值結果都爲 NULL
三、鏈接字符串中含有空值會把NULL做爲 EMPTY STRING
declare
v_deptno dept.deptno%type;
v_loc dept.loc%type;
V_FLAG BOOLEAN ;
V_REC BOOLEAN :=FALSE; --此值改成TRUE、NULL、FALSE進行不一樣的比較
V_AVA BOOLEAN:=NULL;
begin
V_FLAG:=V_REC AND V_AVA;
IF V_FLAG=TRUE THEN
DBMS_OUTPUT.PUT_LINE ('TRUE');
ELSIF V_FLAG=FALSE THEN
DBMS_OUTPUT.PUT_LINE ('FALSE');
ELSE
DBMS_OUTPUT.PUT_LINE ('NULL');
END IF;
end;
/
值得注意的是:NULL AND FALSE ---> FALSE ,這是在實踐中總結出來的。
3、基本循環基礎:
一、LOOP
statement1;
statement2;
. . .
EXIT [WHEN condition];
END LOOP;
v_ord_id s_item.ord_id%TYPE := 101;
v_counter NUMBER (2) := 1;
BEGIN
. . .
LOOP
INSERT INTO s_item (ord_id, item_id)
VALUES (v_ord_id, v_counter);
v_counter := v_counter + 1;
EXIT WHEN v_counter > 10;
END LOOP;
二、FOR循環:
FOR index IN [REVERSE] lower_bound..upper_bound LOOP
statement1;
statement2;
. . .
END LOOP;
實例:
DECLARE
V_LOWER NUMBER:=1;
V_UPPER NUMBER:=23;
BEGIN
DBMS_OUTPUT.PUT_LINE('');
FOR I IN V_LOWER..V_UPPER LOOP
DBMS_OUTPUT.PUT_LINE(I);
END LOOP;
END;
/
三、WHILE 循環:
WHILE condition LOOP
statement1;
statement2;
. . .
END LOOP;
四、循環是能夠多層嵌套的。能夠用<<LABEL>>作循環的標籤。
...
BEGIN
<<Outer–loop>>LOOP
v_counter :=v_counter+1;
EXIT WHEN v_counter>10;
<<Inner–loop>>LOOP
...
EXIT Outer_loop WHEN total_done = ’YES’;
–– Leave both loops
EXIT WHEN inner_done = ’YES’;
–– Leave inner loop only
...
END LOOP Inner_Loop;
...
END LOOP Outer_loop;
END;
總結:本章內容較爲繁雜,雖然不是很難,並且多數與其餘高級語言有某種共性,但你們要多多練習,用實踐來檢驗對某些含糊的猜想。
課程十三 使用組合數據類型* 遊標操縱數據
本課重點:
一、建立用戶自定義的PLSQL記錄
二、利用%ROWTYPE屬性來建立記錄
三、建立PLSQL表
四、描述記錄、表、記錄的表之間的區別
1、合成數據類型
一、類型分爲PLSQL記錄和PLSQL表
二、包含內部組件
三、可重用
2、PLSQL記錄
與3GL中的記錄結構類似,與數據庫表是兩回事
是一個方便的途徑FETCH一些行FROM一個表來進行相關處理。
標準語法格式咱們暫不介紹,由於每本書上均有。
看例子:
declare
vjob varchar(9);
v_count number:=0;
vtotal date:=sysdate +7;
c_tax constant number(3,2):=8.25;
v_valid boolean not null:=true;
ttt vtotal%type;
type emp_record_type is record
(empno number not null:=100,
ename emp.ename%type,
job emp.job%type);
emp_record emp_record_type;
begin
--select sysdate into vtotal from dual;--體會有無此句與結果的影響
dbms_output.put_line (vtotal);
end;
/
主要看TYPE RECORD出現的位置。每個例子都是能夠成功執行的。
咱們也能夠利用原有的表結構:
DECLARE
EMP_RECORD EMP%ROWTYPE;
遊標操縱數據
PLSQL遊標提供了一種從數據庫提取多行數據,而後對每行數據進行單獨處理的方法。
1、兩種遊標:
顯式遊標
隱式遊標
2、顯式遊標:操縱步驟以下:聲明遊標、打開遊標、從遊標中取回數據、關閉遊標
3、聲明遊標:
DECLARE CURSOR_NAME
IS
SELECT STATMENT
可以控制遊標的,惟一參數是INIT.ORA中的OPEN_CURSORS,我原來覺得是客戶端最多能夠打開多少個遊標,但有
本書上講這是用於管理遊標的內存的數量。
DECLARE
CURSOR C_NAME
IS
SELECT ENAME FROM EMP
WHERE DEPTNO IN (SELECT DEPTNO FROM DEPT
WHERE CITY_ID=‘BJ’)
--- 說明遊標能夠用子查詢
4、打開遊標
OPEN CURSOR_NAME;
這時遊標將它的指針指向活動集的開始,指針指向第一條記錄的前面是由於它尚未執行FETCH命令。若是試圖打開一個已經打開的遊標,將出錯:
ORA-06511:PL/SQL:CURSOR ALREADY OPEN
咱們能夠這樣:
IF NOT C_NAME%ISOPEN
THEN
OPEN C_NAME;
END IF;
5、從遊標中取回數據
FETCH CURSOR_NAME INTO RECOR-LIST;
關閉遊標:CLOSE CURSOR_NAME
6、實例:
DECLARE
myname varchar2(22);
CURSOR C_NAME
IS
SELECT ENAME FROM EMP;
begin
IF NOT C_NAME%ISOPEN
THEN
OPEN C_NAME;
end if;
LOOP
FETCH c_name into myname;
dbms_output.put_line (myname);
exit when c_name%notfound;
end loop;
close c_name;
end;
/--咱們將對以上程序進行變形,造成複雜的光標利用。
DECLARE
myname varchar2(22);
thisdeptno scott.emp.deptno%type;
CURSOR C_NAME
IS
SELECT ENAME,deptno FROM EMP order by deptno desc;
begin
IF NOT C_NAME%ISOPEN
THEN
OPEN C_NAME;
end if;
LOOP
FETCH c_name into myname,thisdeptno;
dbms_output.put_line (myname||','||thisdeptno || ',' || to_char(c_name%rowcount));
exit when c_name%notfound;
end loop;
dbms_output.put_line ('the Total record is fetched is ' || to_char(c_name%rowcount));
close c_name;
end;
/
咱們增長變量,進行用了排序,使用了光標屬性,你們看結果發生的變化,想一想爲何。
實例精華!!!:
DECLARE
myname varchar2(22);
ii number;
thisdeptno scott.emp.deptno%type;
CURSOR C_NAME
IS
SELECT * FROM EMP order by deptno desc;
emp_record c_name%rowtype;
begin
ii:=1;
for emp_record in c_name loop
dbms_output.put_line(ii);
ii:=ii+1;
end loop;
end;
/
--這裏使用了遊標FOR循環,在FOR循環的開始,進行、和END LOOP,分別隱式進行了遊標的打開、FETCH和CLOSE。
咱們甚至能夠不聲明遊標:FOR emp_record in (SELECT * FROM DEPT) loop
這種技術被稱爲顯式遊標的自動化。
在上面,咱們能夠將一個表的全部字段輸出,如咱們將PUT_LINE的II改成emp_record.ename,就能夠輸出一個字段內容。
這種方式很是簡單並且效率較高。
----------------
爲了測試光標屬性的重要性,咱們作一個如下的過程:
create or replace PROCEDURE change_salary
(v_emp_id IN NUMBER, -- formal parameters
v_new_salary IN NUMBER)
IS
BEGIN -- begin PL/SQL block
UPDATE emp
SET sal = v_new_salary
WHERE empno = v_emp_id;
COMMIT;
END change_salary;
/
這樣,咱們在匿名塊中,
UPDATE DEPT
SET DNAME='MY DEPT' WHERE ....;
IF SQL%FOUND THEN
COMMIT;
ELSE
change_salary(7369,9000);
END IF;
咱們看到咱們經過流程控制了不一樣的執行結果,對於過程,咱們能夠用如下幾種方法調用:
在SQLPLUS中:
CALL change_salary(7369,9000);
EXECUTE change_salary(7369,9000);
在一個塊中,如:
begin
change_salary(7369,9000);
end;
/
最後一課 異常處理
本章重點:
一、定義PLSQL異常
二、列舉不一樣的異常處理方法
三、捕獲非預期的錯誤
四、描述異常的影響
五、定製異常的返回信息
1、PLSQL異常處理
異常是由ORACLE錯誤或顯式的拋出一個錯誤產生的。
如何處理:用一個處理程序來捕獲它;將它傳遞給CALLING ENVIRONMENT
2、異常的類型:
一、ORACLE SERVER 預約義錯誤
二、非ORACLE SERVER 預約義錯誤,但也是ORACLE SERVER 的標準錯誤
三、用戶自定義異常
3、捕捉異常的要點:
Place the WHEN OTHERS clause after all other exception handling clauses.
You can have at most one WHEN OTHERS clause.
Begin exception-handling section of the block with the keyword EXCEPTION.
Define several exception handlers, each with their own set of actions, for the
block.
When an exception occurs, PL/SQL will process only one handler before leaving
the block.
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
4、經常使用錯誤:
NO_DATA_FOUND ORA-01403
TOO_MANY_ROWS ORA-01422
INVALID_CURSOR ORA-01001
ZERO_DIVIDE ORA-01476
DUP_VAL_ON_INDEX ORA-00001
5、實例
PROCEDURE elim_inventory
(v_product_id IN s_product.id%TYPE) IS
v_id s_product.id%TYPE;
BEGIN
SELECT id INTO v_id FROM s_product WHERE id = v_product_id;
DELETE FROM s_inventory
WHERE product_id = v_product_id;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
ROLLBACK;
TEXT_IO.PUT_LINE(TO_CHAR(v_product_id)||’ is invalid.’);
WHEN TOO_MANY_ROWS THEN
ROLLBACK;
TEXT_IO.PUT_LINE(’Data corruption in S_PRODUCT.’);
WHEN OTHERS THEN
ROLLBACK;
TEXT_IO.PUT_LINE(’Other error occurred.’);
END elim_inventory;
在SCOTT環境中使用要稍加改動
6、使用non-predefined Oracle7 Server error DECLARE E_PRO EXCEPTION; PRAGMA EXCEPTION_INIT(E_PRO,ERROR_NUMBER); BEGIN ...... EXCEPTION WHEN E_PRO THEN DBMS_OUTPUT.PUT_LINE('ASDLKFJKASDJFASJDFLKASDF'); ...... END;