在SQL*plus 中編寫PL/SQL程序,並在SQL*plus 中執行它, PL/SQL塊的代碼就存放在SQL*plus的緩衝區中。
若是在SQL*plus 中執行了其餘的SQL語句或PL/SQL塊,緩衝區中就會存放新的代碼,原來的PL/SQL塊就會被從緩衝區中清除出去。
這種沒有名稱只是臨時存放在緩衝區中的PL/SQL塊叫作匿名塊。
匿名塊就是沒有名字的PL/SQL塊,它僅存放在緩衝區中,只能在當前SQL*plus環境中執行。
若是但願PL/SQL塊能隨時被調用執行,而且能被數據庫用戶共享,就須要建立存儲程序。
存儲程序是有名字的PL/SQL塊,用戶能夠根據它的名字進行屢次調用。sql
存儲程序在建立時通過了編譯與優化,被存放在數據庫中,任何用戶只要有適當的權限,就能夠調用它。
並且在調用時無需再進行編譯,所以能以很快的速度執行。
與匿名塊相比,存儲程序是做爲數據庫對象存儲在數據庫中的,所以,首先要在數據庫中建立存儲程序。數據庫
存儲程序的調用能夠在SQL語句中、應用程序中、SQL*plus 中以及其餘PL/SQL塊中進行。
在第一次被調用時,存儲程序的代碼被裝載到系統全局區的共享池中,之後再次調用時直接從共享池中取出代碼便可執行。
存儲程序與前面介紹的子程序的區別在於子程序是完成某個特定功能的程序段,它自己並不能單燭執行,只能做爲一個模塊,在一個PL/SQL塊內部被調用執行。
而存儲程序是一個可單獨執行的程序,它能夠包含多個子程序,能夠在SQL語句中、應用程序中、SQL*plus 中以及其餘PL/SQL塊中被調用執行。
存儲程序的形式包括:存儲過程、存儲函數、觸發器和程序包等。編程
存儲過程安全
若是用戶要在本身的模式中建立存儲過程,須要具備CREATE PROCEDURE系統權限,若是要在其餘用戶的模式中建立存儲過程,則須要具備CREATE ANY PROCEDURE 系統權限。
建立存儲過程的語法爲:oracle
CREATE OR REPLACE PROCEDURE 過程名(參數1,參數2 ...)ide
AUTHID CURRENT_USER | DEFINER函數
ASoop
聲明部分post
BEGIN優化
可執行部分
EXCEPTION
異常處理部分
END;
其中OR REPLACE選項的做用是當同名的存儲過程存在時,首先將其刪除,再建立新的存儲過程。
固然,條件是當前用戶具備刪除原存儲過程的權限。
存儲過程在建立過程當中已經進行了編譯和優化。
若是須要對存儲過程進行修改,不能直接修改它的源代碼,只能執行CREATE命令從新建立。
存儲過程、存儲函數、程序包都是這樣的狀況。
存儲過程能夠帶有參數,這樣在調用存儲過程時就須要指定相應的實際參數。
若是沒有參數,過程名後面的圓括號和參數列表就能夠省略了。
每一個參數的定義格式爲:
參數名 參數傳遞模式 數據類型 := 默認值
參數各定義中各部分的用法與子程序中的參數徹底相同。
AUTHID 選項用來規定存儲過程執行時的權限。
這個選項有兩個可選值,即CURRENT_USER和DEFINER ,兩者只能選擇其中一個。
過程的執行者和建立者可能不是同一個用戶,若是使用CURRENT_USER建立存儲過程,那麼在調用時,該過程以當前登陸用戶的身份執行。
爲此,過程的建立者必須授予當前用戶執行該過程的權限。
若是以DEFINER建立存儲過程,那麼在調用時,該過程將以建立者身份執行,這是建立存儲過程時默認的選項。
授予其餘用戶執行存儲過程的權限:
GRANT EXECUTE ON 過程名稱 TO 其餘用戶;
用戶在執行其餘用戶的過程時,要在過程名前加上模式名。
在存儲過程當中能夠定義變量、類型、子程序、遊標等元素,定義的方法與在匿名塊中徹底相同。
這裏再也不詳細描述。
存儲過程的聲明部分開始於關鍵宇AS ,結束於關鍵字BEGIN ,並且不須要使用關鍵字DECLARE 。
存儲過程的可執行部分是它的主要部分,它能夠包含SQL語句和流控制語句,是存儲過程功能的集中體現。
異常處理部分用來處理存儲過程在執行過程當中可能出現的錯誤。
例如,下面的代碼用來建立存儲過程total_income ,它的功能是計算某部門員工的總收入。
這個過程有一個參數,表明部門編號,並指定了默認值。
這樣,在調用時,若是提供了參數,則計算指定部門的數據,不然將計算全部員工的數據。
create or replace
PROCEDURE total_income(d_no IN integer:=0)
AUTHID DEFINER
AS
total number;
BEGIN
if d_no=0 then --表示全部部門
SELECT sum(sal+nvl(comm, 0)) INTO total FROM emp;
else --僅表示指定的部門
SELECT sum(sal+nvl(comm, 0)) INTO total
FROM emp
WHERE deptno=d_no;
END if;
dbms_output.put_line ('總收入:'|| total);
END;
存儲過程建立之後,就能夠隨時調用執行了。
在SQL*plus 中調用存儲過程的命令是EXECUTE ,命令的使用格式爲:
EXECUTE 過程名(實際參數)
例如,要計算部門10的員工總收入和應繳的稅,則能夠如下形式調用剛纔建立的存儲過程total income 。
EXECUTE total_income(10)
若是要在一個PL/SQL塊中調用存儲過程,則不須要EXECUTE命令,只要經過過程名和實際參數就能夠調用,調用的格式爲:
過程名(實際參數);
每一個用戶均可以執行本身建立的存儲過程,若是要執行其餘用戶的存儲過程,則須要具備對該存儲過程的EXECUTE權限。
爲此,存儲過程的全部者要將EXECUTE權限授予這個用戶。
授予EXECUTE權限的語句格式爲:
GRANT EXECUTE ON 過程名 TO 用戶;
例如,存儲過程total_income的全部者要將它的執行權限授予用戶scott,則能夠執行下面的SQL語句:
GRANT EXECUTE ON total_income TO scott;
若是要刪除一個存儲過程,能夠執行DROP命令,這個命令的格式爲:
DROP PROCEDURE 過程名
存儲函數
存儲函數也是一種存儲程序,它被建立後便存儲在數據庫中,用戶能夠直接調用。
存儲函數與存儲過程的區別在於,存儲函數必須向調用環境返回一個執行結果。
通常狀況咱們是把存儲函數做爲一個表達式來使用的,它可用於普通表達式可以使用的場合,這是由於每一個函數都有一個返回值,在調用存儲函數時,這個返回值即是存儲函數的執行結果。
例如,能夠將存儲函數賦給一個變量,或者將這個函數與另外一個表達式進行計算等。
建立存儲函數的語法格式爲:
CREATE OR REPLACE FUNCTION 函數名(參數1,參數2 ...)RETURN 返回類型
AUTHID CURRENT_USER | DEFINER
AS
聲明部分
BEGIN
可執行部分
EXCEPTION
異常處理部分
END;
能夠看出,建立存儲函數的格式與建立存儲過程的格式大體相同,只有三個不一樣的地方,第一,用FUNCTION關鍵字代替了PROCEDURE關鍵字,以代表建立的對象是存儲函數,第二,在參數列表以後用RETURN關鍵字規定了存儲函數返回值的類型, 第三,在存儲函數的可執行部分至少有一條RETURN語句,將執行結果返回給調用者。
在存儲函數的可執行部分中,可能會出現多條RETURN語句,用於向調用者返回不一樣的數據,可是通過邏輯處理後,只能有一條RETURN語句被執行,保證從存儲函數中返回一個肯定的數據,這樣就符合了程序的「單出口」的原則。
若是用戶要在本身的模式中建立存儲函數,須要具備CREATE FUNCTION的系統權限,若是要在其餘模式中建立存儲函數,則須要具備CREATE ANY FUNCTION的系統權限。
例如,下面的存儲函數用來計算每一個員工的總收入。
這個函數有兩個參數,即工資和獎金,它的功能是求出工資和獎金之和,而後將結果返回。
建立這個函數的語句爲:
create or replace
FUNCTION total_income_1(sal number,comm number)
RETURN number
AS
result number:=0;
BEGIN
result:=sal+nvl(comm,0);
RETURN result;
END;
若是要利用這個存儲函數求員工的總收入,能夠將這個函數用在SELECT語句中,做爲SELECT語句的一個表達式,而且向它傳遞實際參數,最後獲得它的計算結果。
例如:
SELECT ename,total_income_1(sal,comm) as total FROM emp;
再好比,下面的存儲函數用於計算員工應繳的我的所得稅,這個函數以部門號爲參數,計算該部門中所有員工的所得稅總和。
假設稅率爲3% ,該函數用SUM 函數計算全體員工的工資總和,而後乘以3% ,並將最後的結果返回。
函數的代碼以下所示:
create or replace
FUNCTION tax_per_depart(dno integer) RETURN number
AS
result number:=0;
BEGIN
SELECT sum(sal)*0.03 INTO result FROM emp
WHERE deptno=dno
GROUP BY deptno;
RETURN result;
END;
與其餘存儲函數同樣,這個函數能夠用在SELECT語句中,也能夠在其餘匿名塊、存儲過程、存儲函數中調用執行。
例如,在下面的匿名塊中調用了該函數,計算部門20 的所得稅。
DECLARE
dno integer;
total_tax number;
BEGIN
dno :=20;
total_tax:=tax_per_depart(dno);
dbms_output.put_line('Total tax of department' || dno || 'is:' || total_tax);
END;
每一個用戶均可以直接調用本身建立的存儲函數,若是要調用其餘用戶的存儲函數,則須要具備對相應存儲函數的EXECUTE權限。
爲此,存儲函數的全部者要將EXECUTE權限授予適當的用戶。
授予EXECUTE權限的語句格式爲:
GRANT EXECUTE ON 函數名 TO 用戶名;
例如,存儲函數total_income的全部者要將它的執行權限授予用戶scott,則能夠執行下面的SQL語句:
GRANT EXECUTE ON total_income TO scott;
若是要刪除一個存儲函數,能夠執行DROP命令,這個命令的格式爲:
DROP FUNCTION 函數名;
總之,存儲過程和存儲函數都是存儲程序,它們的區別在於存儲過程沒有返回值,只能被單獨調用執行,在功能上相似於一條命令,而存儲函數有返回值,能夠用在SELECT語句和運算表達式中,它的做用至關於一個普通的表達式。
在存儲過程和存儲函數中均可以定義子程序,這裏把重點放在了存儲過程和存儲函數自己的使用上,對子程序在存儲過程和存儲函數中的用法沒有進行描述,實際上這也是很簡單的。
程序包
程序包是一種Oracle數據庫對象,它是一組邏輯上相關的數據類型、變量、過程、函數和遊標等的集合。
程序包被建立後,存儲在數據庫中,用戶能夠直接使用包中的數據類型和變量,也能夠直接調用包中的過程和函數。
程序包有兩種形式,一種是用戶根據須要建立的程序包,一種是系統預約義的程序包。
這裏介紹自定義程序包的建立、使用、刪除等操做,以及預約義程序包的使用方法。
用戶能夠根據須要建立本身的程序包。
在程序包中能夠定義數據類型、變量、過程、函數、異常和遊標等元素,這些元素具備全局的特性,能夠在程序包中使用,也能夠在程序包以外使用。
一個程序包由兩部分組成:程序包的頭部和包體。
其中頭部用來定義類型、變量、異常、聲明遊標、過程和函數,它的做用至關於程序包的接口。
在包體中能夠利用頭部的類型定義變量,定義過程、遊標和函數的代碼。
在建立程序包時,頭部和包體是分別建立的,而且頭部必須在包體以前建立。
程序包建立以後,若是要對其功能進行修改,這時只需修改包體的代碼便可,不用修改頭部,僅當須要改變參數類型、參數個數等信息時,才須要修改程序包的頭部。
建立程序包頭部的命令是CREATE PACKAGE ,這條命令的語法格式爲:
CREATE [OR REPLACE] PACKAGE 包名稱
AUTHID CURRENT_USER | DEFINER
AS
類型的定義;
變量的定義;
子程序的聲明;
遊標的聲明;
異常的聲明;
END;
其中OR REPLACE選項的做用是當指定的包已經存在時從新建立它。
AUTHID選項用來規定程序包以哪一個用戶的身份執行。
這個選項有兩個可選值,即CURRENT_USER和DEFINER,兩者只能選擇其中一個。
子程序的聲明就是定義過程和函數的原型,即子程序的名稱、參數和返回值,不包含它的代碼部分。
類型定義部分容許用戶根據須要建立本身的數據類型。
例如,要對部門員工的總收入和所得稅進行統計,爲此須要編寫一個程序包。
在程序包中首先定義了一個記錄類型total ,而後聲明瞭一個函數tax_per_depart ,用來統計某個部門的所得稅,過程total_ per_depart用來統計各個部門的員工總收入。
最後還定義了一個遊標c1。
須要注意的是,在程序包的頭部定義遊標時須要指定它的返回類型。
如下是建立程序包employee頭部的代碼:
create or replace
PACKAGE employee
AS
type total is record(
dno emp.deptno%type,
total_income number
);
function tax_per_depart(dno integer) RETURN number;
procedure total_per_depart;
cursor c1 RETURN total;
END;
程序包的包體是對頭部的實現,主要用來定義過程和函數的可執行代碼。
建立包體的命令是CREATE PACKAGE BODY ,這條命令的語法格式爲:
CREATE [OR REPLACE] PACKAGE BODY 包名
AS
遊標的實現;
子程序的實現;
END;
其中包名與建立頭部時使用的名字徹底相同。
遊標的實現是指定遊標中所使用的SELECT語句。
子程序的實現是寫出過程和函數的代碼,過程和函數的編寫方法與之前介紹的方法徹底相同。
如下是建立程序包employee的包體的代碼。
CREATE OR REPLACE PACKAGE BODY employee
AS
CURSOR c1 RETURN total is --定義遊標
SELECT deptno, sum(sal) FROM emp GROUP BY deptno;
FUNCTION tax_per_depart(dno integer) --定義函數tax_per_depart
RETURN number
AS
result number;
BEGIN
SELECT SUM(sal)*0.03 INTO result FROM emp
WHERE deptno=dno;
RETURN result;
END; --函數tax_per_depart結束
PROCEDURE total_per_depart --定義過程total_per_depart
AS
depart TOTAL;
BEGIN
OPEN c1;
FETCH c1 INTO depart; --利用取出遊標中的數據
WHILE c1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('部門'||depart.dno||'總收入'||depart.total_income);
FETCH c1 INTO depart;
END LOOP;
CLOSE c1;
END;
END;
定義了程序包employee後,用戶就能夠在PL/SQL塊或者SQL*Plus 中使用這個包中的類型、遊標、變量、過程和函數了,使用的方法爲:
包名.元素名
例如,要利用程序包employee 中的過程total_per_depart統計各個部門員工的總收入,在SQL*Plus 中調用這個過程:
exec employee.total_per_depart
再好比,在一個匿名塊中調用程序包employee 中的函數tax_per_depart ,計算部門20的所得稅,這個匿名塊的代碼爲:
DECLARE
dno integer;
total_tax number;
BEGIN
dno := 20;
total_tax:=employee.tax_per_depart(dno);
dbms_output.put_line('Total tax of department '||dno||' is: '||total_tax );
END;
若是一個程序包再也不須要,咱們能夠將其從數據庫中刪除。
刪除程序包時,能夠選擇只刪除包體,或者刪除整個包。
刪除整個程序包的命令是DROP PACKAGE ,它的格式爲:
DROP PACKAGE 包名;
這樣,程序包的頭部和包體都將從數據庫中被刪除。
若是隻刪除包體,相應的命令爲DROP PACKAGE BODY ,它的格式爲:
DROP PACKAGE BODY 包名;
系統預約義的程序包
Oracle提供了一些預約義的程序包,利用這些包能夠完成一些複雜的操做。
這些程序包提供了一些經常使用的類型、變量、過程和函數,用戶能夠在PL/SQL塊和應用程序中直接使用它們。
正確地使用這些預約義的程序包,可使開發工做達到事半功倍的效果。
經常使用的預約義程序包及其用途以下所示:
DBMS_OUTPUT 顯示基本的輸入輸出功能
UTL_FILE 對操做系統文件進行讀,寫等操做
DBMS_SQL 執行DDL語句
DBMS_PIPE 用於在兩個進程間以管道方式進行通訊
DBMS_JOB 管理數據庫中的做業
下面將對最經常使用的程序包DBMS_OUTPUT 、UTL_FILE和DBMS_SQL作簡單的介紹。
1. DBMS_OUTPUT程序包
DBMS_OUTPUT包的功能是將PL/SQL塊的執行結果顯示在屏幕上,這種輸出操做是經過緩衝區來完成的。
SQL*Plus 爲存儲程序、PL/SQL塊、觸發器的執行提供了-個緩衝區,用於存放程序執行期間所產生的數據,這個緩衝區以「先進先出」的方式管理其中的數據。
在默認狀況下, PL/SQL塊的執行結果是輸出到緩衝區裏的,若是進行一些特殊的設置,緩衝區中的數據就會輸出到屏幕上,而後從緩衝區中清除。
DBMS_OUTPUT包提供了對緩衝區進行設置、讀和寫等操做的功能,它提供了一系列的過程和函數,分別對緩衝區進行設置、讀和寫等操做。
用戶利用DBMS_ OUTPUT包中的過程或函數能夠向緩衝區中寫人數據,也能夠從緩衝區中讀數據。
緩衝區的設置操做主要包括使其可用和不可用等操做。
使緩衝區不可用的過程是DISABLE,這個過程能夠在SQL*Plus 中以以下形式執行:
EXEC dbms_output.disable
若是要在存儲程序、PL/SQL塊和觸發器中調用這個過程,則不須要EXEC命令,能夠直接調用執行。
與DISABLE相對的操做是ENABLE過程,它可使緩衝區可用,而且能夠設置緩衝區的大小。
它的調用形式爲:
EXEC dbms_output.enable(緩衝區的大小)
若是在調用這個過程時不指定任何參數,則結果是使緩衝區可用,並將其大小設置爲默認大小,即20 000字節。
例如,要將緩衝區的大小設置爲1024字節,這個過程的調用形式爲:
exec dbms_output.enable(1024)
緩衝區的寫操做指的是向緩衝區中寫入數據,目前容許的數據類型有數字型、字符串型和日期型。
寫操做涉及的過程有如下幾個:
•PUT (參數):將指定的參數寫入緩衝區。
•PUT_LINE (參數):將指定的參數寫入緩衝區,並在行末寫一個換行符。
•NEW_LINE :在緩衝區中當前位置處寫一個換行符。
緩衝區中的數據是以行的形式組織的,每行最多存儲255個字符,一行寫滿時,自動從下一行開始繼續寫。
因爲緩衝區的大小有限,寫數據的原則是「先進先出」,當緩衝區寫滿時,若是還要繼續寫,那麼最早寫入緩衝區中的數據就會被從緩衝區中清除出去,以便騰出空間容
納新數據。
PUT和PUT_LINE過程的做用都是向緩衝區當前位置處寫入一行數據,它們之間的區別是,PUT_LINE在寫完數據後在當前行的末尾寫入一個換行符,而PUT過程不寫入換行符。
過程NEW_LINE 的做用僅僅是在緩衝區當前位置處寫入一個換行符。
實際上,調用-次過程PUT_LINE ,至關於先調用一次過程PUT ,而後再調用一次過程NEW_LINE 。
若是要使緩衝區中的數據顯示在顯示器上,必須使選項SERVEROUTPUT有效,這個選項的做用就是使緩衝區中的數據能夠輸出到屏幕上。
爲了使這個選項有效,在SQL*Plus 中執行SET命令:
SET serveroutput ON
這個選項的另外一個可選值是OFF ,它的做用正好與ON相反。
爲了說明這幾個過程的用法,首先觀察下面這個PL/SQL塊的執行狀況:
DECLARE
data1 integer := 100;
data2 varchar2(10) := 'Hello' ;
data3 date DEFAULT sysdate;
BEGIN
dbms_output.put(data1);
dbms_output.put_line(data2);
dbms_output.put_line(data3);
end;
緩衝區的讀操做是指將緩衝區中的數據以行的形式讀出來。
與緩衝區的讀操做有關的過程有兩個:
• GET_LINE :從緩衝區中讀一行。
• GET_LINES :從緩衝區中讀多行。
過程GET_LINE的做用是將目前緩衝區中最早寫入的一行數據讀出,並將這一行數據從緩衝區中刪除。
它的調用形式爲:
GET_LINE(變量,狀態)
其中變量用於存放從緩衝區中讀出的數據,它的類型必須與要讀的數據一致。
狀態也是一個變量,用來表示本次讀操做是否成功,它的傳遞模式爲OUT 。
在這個過程執行結束後,若是狀態變量的值爲0 ,表示成功,若是爲1 ,則表示緩衝區中沒有數據。
過程GET_LINES 的做用是將目前緩衝區中最早寫入的幾行數據讀出,並將它們從緩衝區中刪除。
它的調用形式爲:
GET_LINES(變量,行數)
其中變量是一個集合類型變量,用來存放讀到的幾行數據。
行數也是一個變量,在讀操做以前,這個參數用於指定須要讀的行數,在讀操做以後,這個參數表示實際讀到的數據行數。
下面再經過一個例子說明讀操做和寫操做的綜合應用。
DECLARE
data integer; --表示數據的變量
stat integer; --表示狀態的變量
BEGIN
dbms_output.put(100);
dbms_output.put_line(200);
dbms_output.get_line(data,stat);
dbms_output.put_line ('緩衝區中的數據: ' || data) ;
dbms_output.put_line ('狀態: '|| stat);
END;
DECLARE
data dbms_output.chararr;
stat integer; --表示狀態的變量
BEGIN
dbms_output.put(100);
dbms_output.put_line(200);
stat := 1;
dbms_output.get_lines(data,stat);
for v_counter in 1..stat loop
dbms_output.put_line (data(v_counter)) ;
end loop;
END;
在上述PL/SQL塊中,第一次向緩衝區中寫100時使用了過程PUT ,寫人數據後沒有換行。
第二次向緩衝區中寫200時使用了過程PUT LINE ,這樣100和200被寫在了同一行。
在讀數據時使用了過程GET_LINE ,將剛纔寫人的一行數據讀到變量data 中,因而變量data的值爲100 200 。
而變量stat用來表示本次讀操做是否成功,其值爲0 ,表示讀操做成功。
因而可知,在從緩衝區中讀數據時,是以行爲單位進行的,而不是以數據爲單位。
實際上, DBMS_OUTPUT程序包自己並無輸入輸出的功能,它所能作的就是對緩衝區進行讀寫操做。
若是使SERVEROUTPUT選項有效,則緩衝區的內容就被輸出到屏幕上, PUT和PUT_LINE過程只須要把數據寫入緩衝區中就能夠了,這就至關於完成了輸出工做。
而GET_LINE的功能是從緩衝區中讀一行數據,若是緩衝區中有數據,則它把當前緩衝區中最早寫入的數據讀出,這就至關於完成了輸入工做。
2. UTL_FILE程序包
UTL_FILE程序包功能是對本地操做系統的文件進行訪問。
在PL/SQL塊中訪問文件的能力是有限的,主要包括文件的打開、關閉、讀、寫等操做。
在訪問文件以前,必須先打開文件,這時系統將返回一個文件標識,對文件的讀、寫等操做都是經過這個文件標識進行的。
文件訪問完後,還應該及時關閉文件。
UTL_FILE程序包中與文件的打開和關閉操做有關的函數和過程有:
• FOPEN
•IS_OPEN
• FCLOSE
• FCLOSE ALL
在訪問文件以前,首先要用函數FOPEN打開文件。
這個函數的調用格式爲:
FOPEN(目錄,文件名,打開模式)
其中目錄爲文件所在的位置,它與文件名一塊兒肯定了要訪問的文件。
打開模式是指以什麼樣的方式打開文件。
UTL_FILE包規定了三種打開模式:
• r :只讀方式,用於讀出文件的內容。
•w :寫方式,用於向文件中寫入數據。
•a :追加方式,用於在文件末尾寫入數據。
UTL_FILE程序包訪問文件的功能頗有限,並非全部的文件均可以訪問。
利用這個程序包只能訪問指定目錄中的文本文件。
爲了訪問某個目錄中的文件,必須經過初始化參數指定這個目錄,指定的格式爲:
UTL_FILE_DIR=目錄
例如,爲了訪問目錄/home/oracle中的文件,須要在參數文件中添加一下內容:
UTL_FILE_DIR=/home/oracle
若是沒有初始化參數指定目錄,那麼在訪問一個目錄中的文件時, Oracle將拋出一個預約義的異常UTL_FILE.INVALID PATH 。
若是要訪問全部目錄中的文件,能夠用「*」表明任何目錄,代替上面某個具體目錄,但這種做法是不提倡的,由於這將帶來安全隱患。
若是文件打開成功, FOPEN 函數將返回一個FILE_TYPE類型的文件標識,之後對文件的訪問就是經過這個文件標識進行的。
FILE_TYPE類型是在UTL_FILE包中定義的類型,用戶能夠直接使用。
函數IS_OPEN用於判斷一個文件是否已經被打開,它只有一個參數,就是FOPEN 函數返回的文件標識。
若是文件已經被打開,函數IS_OPEN將返回真值,不然返回假值。
文件訪問結束後,應該調用過程FCLOSE關閒文件。
這個過程只有一個參數,就是FOPEN函數返回的文件標識。
若是打開了多個文件,能夠調用過程FCLOSE ALL關閉全部文件,這個過程沒有任何參數。
與文件的讀操做有關的過程爲GET_LINE ,它的調用格式爲:
GET_LINE(文件標識,變量)
其中文件標識就是用函數FOPEN打開文件時的返回值。
變量是一個字符串類型的變量,用於存放從文件中讀到的數據。
由於對文件的讀操做是以行爲單位進行的,因此這個變量要可以存放文件中的一行數據。
若是一個文件是空的,或者當前已經讀到了文件末尾,這時系統將拋出異常NO_DATA_FOUND 。
下面的例子演示了文件的打開、讀和關閉操做。
文件打開後將它的第一行數據讀出,並輸出到顯示器上。
DECLARE
fp UTL_FILE.FILE_TYPE;
line VARCHAR2(100);
BEGIN
fp := UTL_FILE.FOPEN('C:\Users\Administrator\Desktop', 'a.log', 'r');
UTL_FILE.GET_LINE(fp, line);
DBMS_OUTPUT.PUT_LINE(line);
UTL_FILE.FCLOSE(fp);
END;
對文件的寫操做涉及的過程較多,這裏僅介紹用得最多的過程PUT_LINE 。
這個過程以行的形式將數據寫入文件,每寫入一行,就在行的末尾添加一個換行符,它的調用形式爲:
PUT_LINE(文件標識,變量)
這個過程將變量中的數據寫入文件標識所表明的文件中。
在下面的例子中,首先以只讀方式打開第一個文件,而後以追加方式打開第二個文件。
從第一個文件中讀一行數據到變量中,在這行數據的先後各添加一個「#」 後再寫入第二個文件,最後關閉兩個文件。
DECLARE
fp1 UTL_FILE.FILE_TYPE;
fp2 UTL_FILE.FILE_TYPE;
line VARCHAR2(100);
BEGIN
fp1 := UTL_FILE.FOPEN('C:\Users\Administrator\Desktop', 'a.log', 'r');
fp2 := UTL_FILE.FOPEN('C:\Users\Administrator\Desktop', 'a.bak', 'a');
UTL_FILE.GET_LINE(fp1, line);
UTL_FILE.PUT_LINE(fp2, '#'||line||'#');
UTL_FILE.FCLOSE_ALL;
END;
3. DBMS_SQL包
在PL/SQL塊中咱們能夠利用SELECT命令從數據庫中檢索數據,也能夠利用INSERT 、DELETE和UPDATE語句對數據庫中的數據進行增長、刪除、修改等操做。
可是像建立表、刪除表、修改表結構這樣的操做在PL/SQL塊中是不能直接完成的,也就是說,在PL/SQL塊中不能直接執行CREATE 、DROP 、ALTER這樣的DDL命令。
若是要在PL/SQL塊中進行這樣的操做,就要藉助於Oracle提供的程序包一-DBMS_SQL 。
DBMS_SQL包使得在PL/SQL包中執行DDL命令成爲可能。
利用DBMS_SQL包執行DDL命令時,首先要打開一個遊標,而後經過這個遊標執行DDL命令,最後關閉這個遊標。
DBMS_SQL包提供了一系列的過程和函數,利用這些過程和函數能夠完成所需的操做。
用來打開遊標的函數是OPEN_CURSOR ,這個函數沒有任何參數。
若是遊標打開成功,這個函數將返回一個整數,這個整數就是遊標的標識。
之後執行SQL語句就是經過這個遊標的標識進行的。
對SQL語句進行分析的過程是PARSE ,這個過程對SQL語句進行語法分析,將其與打開的遊標、進行關聯,而後執行這條SQL語句。
這個過程的調用格式爲:
PARSE (遊標標識, SQL語句,語言標誌)
其中游標標識就是打開遊標時的返回值。
SQL語句是須要執行的DDL命令的完整形式。
語言標誌指定該過程以什麼樣的方式處理SQL語句,這個參數有三個可選值:
• DBMS_SQL.V6 :採用Oracle6的方式處理SQL語句。
• DBMS_SQL.V7 :採用Oracle7的方式處理SQL語句。
• DBMS_SQL.NATIVE :採用通常方式處理SQL語句。
SQL語句執行結束後,應該及時關閉遊標。
關閉遊標的過程是CLOSE_CURSOR ,這個過程只有一個參數,就是經過函數OPEN_CURSOR打開的遊標的標識。
例如,在下面的PL/SQL塊中,首先打開一個遊標,遊標的標識爲cur_1 ,而後利用這個遊標執行一條SQL語句,建立表tl ,這個表有兩個列, id和name 。
最後關閉這個遊標。
這個塊的執行結果是在當前用戶的模式中建立了一個表t1 。
DECLARE
cur_1 integer;
str varchar2(100);
BEGIN
str := 'CREATE table t1(id integer,name varchar2(10 ))';
cur_1:=dbms_sql.open_cursor;
dbms_sql.parse(cur_1,str,DBMS_SQL.V7);
dbms_sql.close_cursor(cur_1);
END;
若是已經有一個同名的表存在,上述PL/SQL塊執行時將出錯。
爲了向用戶報告出錯的狀況,能夠在PL/SQL塊中捕捉錯誤,並進行異常處理,將出錯的狀況報告給用戶,這樣的PL/SQL塊纔算是一個完整的、健壯的程序。
下面是增長了異常處理的PL/SQL塊:
DECLARE
cur_1 integer;
str varchar2(100);
already_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(already_exists,-00955);
BEGIN
str := 'CREATE table t1(id integer,name varchar2(10 ))';
cur_1:=dbms_sql.open_cursor;
dbms_sql.parse(cur_1,str,DBMS_SQL.V7);
dbms_sql.close_cursor(cur_1);
EXCEPTION
WHEN already_exists THEN
dbms_output.put_line ('須要建立的表已經存在');
END;
在這個塊中定義了一個異常already_exists ,而後將它與錯誤號,-00955 關聯起來。
錯誤號-0955表明的錯誤狀況是指定的名稱已經被其餘對象使用。
這樣當發生這個錯誤時,系統將拋出異常already_exists 。
在塊的最後,進行的異常的處理,將錯誤的狀況顯示給用戶。
實際上,在PL/SQL塊中還有一種執行DDL和DCL語句的方法,那就是把這樣的語句做爲EXECUTE IMMEDIATE命令的參數。
EXECUTE IMMEDIATE命令的功能是執行動態的SQL語句,它的參數能夠是一個變量或一個表示SQL語句的字符串,還能夠是用「||」符號鏈接在一塊兒的若干字符串等。
例如:
declare
sql_stmt varchar2(100) := ' CREATE TABLE t1(id number,name char(10))';
begin
EXECUTE IMMEDIATE sql_stmt;
EXECUTE IMMEDIATE ' GRANT select,update on t1 to shu';
EXECUTE IMMEDIATE 'DROP TABLE t1';
end;
與存儲程序有關的數據字典
在數據庫中,存儲過程、存儲函數以及程序包的信息是存放在數據字典中的。
與存儲程序有關的數據字典有:
USER_PROCEURES
USER_OBJECTS
USER_SOURCE
USER_ERROR
下面是有關數據字典ALL_PROCEDURES的介紹:
ALL_PROCEDURES
lists all functions and procedures that are accessible(可訪問的) to the current user, along with associated properties(與之關聯的屬性).
For example,ALL_PROCEDURES
indicates whether or not a function is pipelined, parallel enabled or an aggregate function(代表一個函數是不是一個管道類型的,可並行或者是一個彙集函數).
If a function is pipelined or an aggregate function, the associated implementation type(關聯的實現類型) (if any(若是有的話)) is also identified(識別).
Related Views
DBA_PROCEDURES
lists all functions and procedures available in the database, along with associated properties.
USER_PROCEDURES
lists all functions and procedures owned by the current user, along with associated properties.It does not contain the OWNER
column.
Column | Datatype | NULL | Description |
---|---|---|---|
|
|
Owner of the procedure |
|
|
|
Name of the object: top-level function, procedure, or package name |
|
|
|
Name of the procedure |
|
|
|
Object number of the object |
|
|
|
Unique subprogram identifier(惟一子程序標識) |
|
|
|
Overload unique identifier |
|
|
|
The typename of the object |
|
|
|
Indicates whether the procedure is an aggregate function ( |
|
|
|
Indicates whether the procedure is a pipelined table function(管道表函數) ( |
|
|
|
Owner of the implementation type(實現類型), if any |
|
|
|
Name of the implementation type, if any |
|
|
|
Indicates whether the procedure or function is parallel-enabled ( |
|
|
|
|
|
|
|
|
|
|
|
Indicates whether the procedure/function is declared to execute as |
|
|
|
The ID of the container where the data originates. Possible values include:
|
例如:要想查看當前用戶所擁有的存儲過程和存儲函數,執行下面的SELECT語句:
SELECT object_name, object_type, authid FROM user_procedures;
數據字典user_objects用來存放當前用戶所擁有的全部類型的數據庫對象,包括表、視圖、觸發器、序列、存儲過程、存儲函數以及程序包等。
下面是有關數據字典ALL_OBJECTS的介紹:
ALL_OBJECTS
describes all objects accessible to the current user.
Related Views
DBA_OBJECTS
describes all objects in the database.
USER_OBJECTS
describes all objects owned by the current user. This view does not display the OWNER
column.
Column | Datatype | NULL | Description |
---|---|---|---|
|
|
|
Owner of the object |
|
|
|
Name of the object |
|
|
Name of the subobject(子對象) (for example, partition) |
|
|
|
|
Dictionary object number of the object |
|
|
Dictionary object number of the segment that contains the object. Note: |
|
|
|
Type of the object (such as |
|
|
|
|
Timestamp for the creation of the object |
|
|
|
Timestamp for the last modification of the object and dependent objects(依賴對象) resulting from a DDL statement (including grants and revokes) |
|
|
Timestamp for the specification of the object (對象的時間戳格式)(character data) |
|
|
|
Status of the object:
|
若是要了解當前用戶所擁有的數據庫對象類型,能夠執行下面的SELECT語句:
SELECT DISTINCT object_type FROM user_objects;
程序包的頭部和包體的類型分別爲PACKAGE和PACKAGE BODY 。
若是要查看某個數據庫對象的詳細信息,一樣能夠執行相應的SELECT語句。
例如,如下SELECT語句用來查看對象「total_income」的詳細信息:
SELECT object_name, object_type, status, created FROM user_objects WHERE object_name='TOTAL_INCOME';
數據字典user_source用來存放存儲過程、存儲函數和程序包的源代碼。
固然,這個視圖的目的只是爲了查看源代碼, PL/SQL程序的執行並非從這裏開始的,由於程序在建立時已經通過了編譯,在數據庫中以二進制形式存儲。
所以,試圖經過修改這個數據字典而達到修改存儲程序的功能是行不通的。
Oracle在建立PL/SQL程序時,將按照用戶在編寫時的天然格式,以行的形式存儲程序代碼,並記錄每行的行號,全部代碼行合起來就是該程序的源代碼。
下面是有關數據字典ALL_SOURCE的介紹:
ALL_SOURCE
describes the text source of the stored objects accessible to the current user.
Related Views
DBA_SOURCE
describes the text source of all stored objects in the database.
USER_SOURCE
describes the text source of the stored objects owned by the current user. This view does not display the OWNER
column.
Column | Datatype | NULL | Description |
---|---|---|---|
OWNER |
VARCHAR2(30) |
NOT NULL |
Owner of the object |
NAME |
VARCHAR2(30) |
NOT NULL |
Name of the object |
TYPE |
VARCHAR2(12) |
Type of object: FUNCTION , JAVA SOURCE , PACKAGE , PACKAGE BODY , PROCEDURE , TRIGGER ,TYPE , TYPE BODY |
|
LINE |
NUMBER |
NOT NULL |
Line number of this line of source |
TEXT |
VARCHAR2(4000) |
Text source of the stored object |
例如,要查看函數tax_per_depart的源代碼,能夠執行下列SELECT語句:
SELECT line, text FROM user_source WHERE name='TOTAL_INCOME';
若是在建立存儲過程、存儲函數或者程序包時發生了語法錯誤, SQL*Plus將把錯誤信息在屏幕上顯示,同時Oraclet把錯誤信息記錄在數據字典中。
數據字典user_errors就是用來存放當前用戶在建立存儲程序時發生的錯誤的。
下面是有關數據字典ALL_ERRORS的介紹:
ALL_ERRORS
describes the current errors on the stored objects accessible to the current user.
Related Views
DBA_ERRORS
describes the current errors on all stored objects in the database.
USER_ERRORS
describes the current errors on the stored objects owned by the current user. This view does not display the OWNER
column.
Column | Datatype | NULL | Description |
---|---|---|---|
OWNER |
VARCHAR2(30) |
NOT NULL |
Owner of the object |
NAME |
VARCHAR2(30) |
NOT NULL |
Name of the object |
TYPE |
VARCHAR2(12) |
Type of the object:
|
|
SEQUENCE |
NUMBER |
NOT NULL |
Sequence number (for ordering purposes) |
LINE |
NUMBER |
NOT NULL |
Line number at which the error occurred |
POSITION |
NUMBER |
NOT NULL |
Position in the line at which the error occurred |
TEXT |
VARCHAR2(4000) |
NOT NULL |
Text of the error |
ATTRIBUTE |
VARCHAR2(9) |
Indicates whether the error is an error (ERROR ) or a warning (WARNING ) |
|
MESSAGE_NUMBER |
NUMBER |
Numeric error number (without any prefix)(數字錯誤號,沒有任何前綴) |
例如,在建立存儲函數total_income時,錯把SELECT
語句中的「WHERE deptno=d_no」寫成了「 WHERE deptno=ddn。」,因而發生了錯誤:
CREATE OR REPLACE PROCEDURE total_income(d_no IN integer:=0)
AUTHID DEFINER
AS
total number;
BEGIN
if d_no=0 then --表示全部部門
SELECT sum(sal+nvl(comm, 0)) INTO total FROM emp;
else --僅表示指定的部門
SELECT sum(sal+nvl(comm, 0)) INTO total
FROM emp
WHERE deptno=ddn;
END if;
dbms_output.put_line ('總收入:'|| total);
END;
Warning: Procedure created with compilation errors
爲了肯定發生的全部錯誤的位置,執行下列查詢語句:
SELECT sequence, line, position FROM user_errors;
爲了查看第一個錯誤的詳細信息,須要檢索TEXT列的數據:
根據這些錯誤信息很快即可以肯定錯誤的緣由,從而進行糾正。
在不少狀況下,發生的多個錯誤是由同一個緣由引發的,只要修改了出現錯誤的程序代碼,多個錯誤可能一塊兒消失。
這須要用戶在編寫程序的過程當中不斷積累經驗。
SQL*Plus還提供了一種查看錯誤信息的簡便方法,用show errors命令能夠查看當前發生的錯誤,而不須要了解數據字典的詳細結構。
這個命令的用法爲:
SHOW ERRORS
或者在查看錯誤信息時指定發生錯誤的對象的類型和名稱,如:
SHOW ERRORS FUNCTION total_income
在這種狀況下,命令show errors的格式爲:
SHOW ERRORS 對象類型 對象名稱