Oracle數據庫操作處理筆記(3)

一、存儲過程/job/函數/觸發器操作
1、存儲過程和函數
存儲過程和函數也是一種 pl/sql塊,是存入數據庫的 pl/sql塊。但存儲過程和函數不同於已經介紹過的 pl/sql程序,我們通常把 pl/sql程序稱爲無名塊,而存儲過程和函數是以命名的方式存儲於數據庫中的。和 pl/sql程序相比,存儲過程有很多優點,具體歸
納如下:
a)存儲過程和函數以命名的數據庫對象形式存儲於數據庫當中。存儲在數據庫中的優點是很明顯的,因爲代碼不保存在本地,用戶可以在任何客戶機上登錄到數據庫,並調用或修改代碼。
b)存儲過程和函數可由數據庫提供安全保證,要想使用存儲過程和函數,需要有存儲過程和函數的所有者的授權,只有被授權的用戶或創建者本身才能執行存儲過程或調用函數。
c)存儲過程和函數的信息是寫入數據字典的,所以存儲過程可以看作是一個公用模塊,用戶編寫的 pl/sql程序或其他存儲過程都可以調用它(但存儲過程和函數不能調用 pl/sql程序)。一個重複使用的功能,可以設計成爲存儲過程,比如:顯示一張工資統計表,可以設計成爲存儲過程;一個經常調用的計算,可以設計成爲存儲函數;根據僱員編號返回僱員的姓名,可以設計成存儲函數。
d)像其他高級語言的過程和函數一樣,可以傳遞參數給存儲過程或函數,參數的傳遞也有多種方式。存儲過程可以有返回值,也可以沒有返回值,存儲過程的返回值必須通過參數帶回;函數有一定的數據類型,像其他的標準函數一樣,我們可以通過對函數名的調用返回函數值。
存儲過程和函數需要進行編譯,以排除語法錯誤,只有編譯通過才能調用。
創建存儲過程,需要有 create procedure或 create any procedure的系統權限。該權限可由系統管理員授予。創建一個存儲過程的基本語句如下:

create [or replace] procedure存儲過程名[(參數[in|out|in out]數據類型...)]
{as|is}
[說明部分]
begin
可執行部分
[exception
錯誤處理部分]
end [過程名];

其中:可選關鍵字 or replace表示如果存儲過程已經存在,則用新的存儲過程覆蓋,通常用於存儲過程的重建。參數部分用於定義多個參數(如果沒有參數,就可以省 略)。參數有三種形式:in、out和 in out。如果沒有指明參數的形式,則默認爲 in,關鍵字 as也可以寫成 is,後跟過程的說明部分,可以在此定義過程的局部變量,編寫存儲過程可以使用任何文本編輯器或直接在 sqlplus環境下進行,編寫好的存儲過程必須要在 sqlplus環境下進行編譯,生成編譯代碼,原代碼和編譯代碼在編譯過程中都會被存入數據庫。編譯成功的存儲過程就可以在 oracle環境下進行調用了。一個存儲過程在不需要時可以刪除。刪除存儲過程的創建者或者擁有 drop any procedure系統權限的人。刪除存儲過程的語法如下:

語法格式:drop procedure存儲過程名;

如果要重新編譯一個存儲過程,則只能是過程的創建者或者擁有 alter any procedure系統權限的人。語法如下:

alter procedure存儲過程名 compile;

執行(或調用)存儲過程的人是過程的創建者或是擁有 execute any procedure系統權限的人或是被擁有者授予 execute權限的人。執行的方法如下:

方法 1:
execute模式名.存儲過程名[(參數...)];
方法 2:
begin
模式名.存儲過程名[(參數...)];
end;

【訓練 1】創建一個顯示僱員總人數的存儲過程。
步驟 1:登錄 scott賬戶(或學生個人賬戶)。
步驟 2:在 sql*plus輸入區中,輸入以下存儲過程:

create or replace procedure dyk_count
as
v_total1 number(10);
v_total2 number(10);
v_total3 number(10);
begin
select count(*) into v_total1 from dyk_table1;
dbms_output.put_line('僱員總人數爲:'||v_total1);
delete dyk_table1 where owner In ('XDB','CTSSYS','OUTLN','WMSYS');
select count(*) into v_total2 from dyk_table1;
dbms_output.put_line('剩餘總人數爲:'||v_total2);
insert into dyk_table1 nologging select * from dba_objects;
select count(*) into v_total3 from dyk_table1;
dbms_output.put_line('增加後的總人數爲:'||v_total3);
end;

步驟 3:按“執行”按鈕進行編譯。
如果存在錯誤,就會顯示:警告:創建的過程帶有編譯錯誤。
如果存在錯誤,對腳本進行修改,直到沒有錯誤產生。
如果編譯結果正確,將顯示:(sql代碼)
過程已創建。
步驟 4:調用存儲過程,在輸入區中輸入以下語句並執行:
sql代碼

set serverout on  /從 sql提示符下輸出存儲過程變量值
execute dyk_count;
顯示結果爲:
僱員總人數爲:337386
剩餘總人數爲:336456
增加後的總人數爲:386254

說明:在該訓練中,v_total變量是存儲過程定義的局部變量,用於接收查詢到的僱員總人數。
注意:在 sql*plus中輸入存儲過程,按“執行”按鈕是進行編譯,不是執行存儲過程。如果在存儲過程中引用了其他用戶的對象,比如表,則必須有其他用戶授予的對象訪問權限。一個存儲過程一旦編譯成功,就可以由其他用戶或程序來引用。但存儲過程或函數的所有者必須授予其他用戶執行該過程的權限。
存儲過程沒有參數,在調用時,直接寫過程名即可。

【訓練 2】在 pl/sql程序中調用存儲過程。
步驟 1:登錄 scott賬戶。
步驟 2:授權 student賬戶使用該存儲過程,即在 sql*plus輸入區中,輸入以下的命令:
sql代碼

grant execute on emp_count to student;

sql代碼
授權成功。
步驟 3:登錄 student賬戶,在 sql*plus輸入區中輸入以下程序:
sql代碼

set serveroutput on
begin
scott.emp_count;
end;

步驟 4:執行以上程序,結果爲:
sql代碼
僱員總人數爲:14
pl/sql過程已成功完成。

說明:在本例中,存儲過程是由 scott賬戶創建的,studen賬戶獲得 scott賬戶的授權後,才能調用該存儲過程。
注意:在程序中調用存儲過程,使用了第二種語法。

【訓練 3】編寫顯示僱員信息的存儲過程 emp_list,並引用 emp_count存儲過程。

步驟 1:在 sql*plus輸入區中輸入並編譯以下存儲過程:
sql代碼

create or replace procedure emp_list
as
cursor emp_cursor is
select empno,ename from emp;
begin
for emp_record in emp_cursor loop
dbms_output.put_line(emp_record.empno||emp_record.ename);
end loop;
emp_count;
end;

過程已創建。

步驟 2:調用存儲過程,在輸入區中輸入以下語句並執行:
sql代碼

execute emp_list


execute emp_list
顯示結果爲:
sql代碼
7369smith
7499allen
7521ward
7566jones
執行結果:
僱員總人數爲:14
pl/sql過程已成功完成。

說明:以上的 emp_list存儲過程中定義並使用了遊標,用來循環顯示所有僱員的信息。然後調用已經成功編譯的存儲過程emp_count,用來附加顯示僱員總人數。通過 execute命令來執行 emp_list存儲過程。

【練習 1】編寫顯示部門信息的存儲過程 dept_list,要求統計出部門個數。
參數傳遞:參數的作用是向存儲過程傳遞數據,或從存儲過程獲得返回結果。正確的使用參數可以
大大增加存儲過程的靈活性和通用性,參數的類型有三種,如下所示。
sql代碼

in定義一個輸入參數變量,用於傳遞參數給存儲過程
out定義一個輸出參數變量,用於從存儲過程獲取數據
in out定義一個輸入、輸出參數變量,兼有以上兩者的功能

in定義一個輸入參數變量,用於傳遞參數給存儲過程
out定義一個輸出參數變量,用於從存儲過程獲取數據
in out定義一個輸入、輸出參數變量,兼有以上兩者的功能

參數的定義形式和作用如下:
參數名 in數據類型 default值;
定義一個輸入參數變量,用於傳遞參數給存儲過程。在調用存儲過程時,主程序的實際參數可 以是常量、有值變量或表達式等。default關鍵字爲可選項,用來設定參數的默認值。如果在調用存儲過程時不指明參數,則參數變量取默認值。在存儲過程中,輸入變量接收主程序傳遞的值,但不能對其進行賦值。
參數名 out數據類型;
定義一個輸出參數變量,用於從存儲過程獲取數據,即變量從存儲過程中返回值給主程序。
在調用存儲過程時,主程序的實際參數只能是一個變量,而不能是常量或表達式。在存儲過程中,參數變量只能被賦值而不能將其用於賦值,在存儲過程中必須給輸出變量至少賦值一次。
參數名 in out數據類型 default值;
定義一個輸入、輸出參數變量,兼有以上兩者的功能。在調用存儲過程時,主程序的實際參數只能是一個變量,而不能是常量或表達式。default關鍵字爲可選項,用來設定參數的默認值。在存儲過程中,變量接收主程序傳遞的值,同時可以參加賦值運算,也可以對其進行賦值。在存儲過程中必須給變量至少賦值一次。
如果省略 in、out或 in out,則默認模式是 in。
【訓練 1】編寫給僱員增加工資的存儲過程 change_salary,通過 in類型的參數傳遞要增加工資的僱員編號和增加的工資額。
步驟 1:登錄 scott賬戶。
步驟 2:在 sql*plus輸入區中輸入以下存儲過程並執行:
sql代碼

create or replace procedure change_salary(p_empno in number default 7788,p_raise number default 10)
as
v_ename varchar2(10);
v_sal number(5);
begin
select ename,sal into v_ename,v_sal from emp where empno=p_empno;
update emp set sal=sal+p_raise where empno=p_empno;
dbms_output.put_line('僱員'||v_ename||'的工資被改爲'||to_char(v_sal+p_raise));
commit;
exception
when others then
dbms_output.put_line('發生錯誤,修改失敗!');
rollback;
end;
過程已創建。

步驟 3:調用存儲過程,在輸入區中輸入以下語句並執行:
sql代碼

execute change_salary(7788,80);

顯示結果爲:
sql代碼
僱員 scott的工資被改爲 3080
說明:從執行結果可以看到,僱員 scott的工資已由原來的 3000改爲 3080。
參數的值由調用者傳遞,傳遞的參數的個數、類型和順序應該和定義的一致。如果順序不一致,可以採用以下調用方法。如上例,執行語句可以改爲:

execute change_salary(p_raise=>80,p_empno=>7788);

可以看出傳遞參數的順序發生了變化,並且明確指出了參數名和要傳遞的值,=>運算符左側是參數名,右側是參數表達式,這種賦值方法的意義較清楚。
【練習 1】創建插入僱員的存儲過程 insert_emp,並將僱員編號等作爲參數。
在設計存儲過程的時候,也可以爲參數設定默認值,這樣調用者就可以不傳遞或少傳遞參數了。

【訓練 2】
調用存儲過程 change_salary,不傳遞參數,使用默認參數值。
在 sql*plus輸入區中輸入以下命令並執行:
sql代碼

execute change_salary
顯示結果爲:
sql代碼
僱員 scott的工資被改爲 3090

說明:在存儲過程的調用中沒有傳遞參數,而是採用了默認值 7788和 10,即默認僱員號爲 7788,增加的工資爲 10。

【訓練 3】使用 out類型的參數返回存儲過程的結果。
步驟 1:登錄 scott賬戶。
步驟 2:在 sql*plus輸入區中輸入並編譯以下存儲過程:
sql代碼

create or replace procedure emp_count(p_total out number)
as
begin
select count(*) into p_total from emp;
end;

執行結果爲:
sql代碼
過程已創建。

步驟 3:輸入以下程序並執行:
sql代碼

declare
v_empcount number;
begin
emp_count(v_empcount);
dbms_output.put_line('僱員總人數爲:'||v_empcount);
end;

顯示結果爲:
sql代碼
僱員總人數爲:14
pl/sql過程已成功完成。

說明:在存儲過程中定義了 out類型的參數 p_total,在主程序調用該存儲過程時,傳遞了參數v_empcount。在存儲過程中的 select…into…語句中對 p_total進行賦值,賦值結果由 v_empcount 變量帶回給主程序並顯示。
以上程序要覆蓋同名的 emp_count存儲過程,如果不使用 or replace選項,就會出現以下錯誤:
sql代碼
error位於第 1行:
ora-00955:名稱已由現有對象使用。

【練習 2】創建存儲過程,使用 out類型參數獲得僱員經理名。

【訓練 4】使用 in out類型的參數,給電話號碼增加區碼。
步驟 1:登錄 scott賬戶。
步驟 2:在 sql*plus輸入區中輸入並編譯以下存儲過程:
sql代碼

create or replace procedure add_region(p_hpone_num in out varchar2)
as
begin
p_hpone_num:='0755-'||p_hpone_num;
end;

執行結果爲:
過程已創建。
步驟 3:輸入以下程序並執行:
sql代碼

set serveroutput on
declare
v_phone_num varchar2(15);
begin
v_phone_num:='26731092';
add_region(v_phone_num);
dbms_output.put_line('新的電話號碼:'||v_phone_num);
end;

顯示結果爲:
sql代碼
新的電話號碼:0755-26731092
pl/sql過程已成功完成。

說明:變量 v_hpone_num既用來向存儲過程傳遞舊電話號碼,也用來向主程序返回新號碼。新的號碼在原來基礎上增加了區號 0755和-。
創建和刪除存儲函數

創建函數,需要有 create procedure或 create any procedure的系統權限。該權限可由系統管理員授予。創建存儲函數的語法和創建存儲過程的類似,即

create [or replace] function函數名[(參數[in]數據類型...)]
return數據類型
{as|is}
[說明部分]
begin
可執行部分
return (表達式)
[exception
錯誤處理部分]
end [函數名];

其中,參數是可選的,但只能是 in類型(in關鍵字可以省略)。
在定義部分的 return數據類型,用來表示函數的數據類型,也就是返回值的類型,此部分不可省略。在可執行部分的 return(表達式),用來生成函數的返回值,其表達式的類型應該和定義部分說明的函數返回值的數據類型一致。在函數的執行部分可以有多個 return語句,但只有一個 return語句會被執行,一旦執行了 return語句,則函數結束並返回調用環境。
一個存儲函數在不需要時可以刪除,但刪除的人應是函數的創建者或者是擁有 drop any procedure系統權限的人。其語法如下:

drop function函數名;

重新編譯一個存儲函數時,編譯的人應是函數的創建者或者擁有 alter any procedure系統權限的人。重新編譯一個存儲函數的語法如下:

alter procedure函數名 compile;

函數的調用者應是函數的創建者或擁有 execute any procedure系統權限的人,或是被函數的擁有者授予了函數執行權限的賬戶。函數的引用和存儲過程不同,函數要出現在程序體中,可以參加表達式的運算或單獨出現在表達式中,其形式如下:
變量名:=函數名(…)

【訓練 1】創建一個通過僱員編號返回僱員名稱的函數 get_emp_name。
步驟 1:登錄 scott賬戶。
步驟 2:在 sql*plus輸入區中輸入以下存儲函數並編譯:
sql代碼

create or replace function get_emp_name(p_empno number default 7788)
return varchar2
as
v_ename varchar2(10);
begin
elect ename into v_ename from emp where empno=p_empno;
return(v_ename);
exception
when no_data_found then
dbms_output.put_line('沒有該編號僱員');
return (null);
when too_many_rows then
dbms_output.put_line('有重複僱員編號!');
return (null);
when others then
dbms_output.put_line('發生其他錯誤!');
return (null);
end; 

步驟 3:調用該存儲函數,輸入並執行以下程序:
sql代碼

begin
dbms_output.put_line('僱員 7369的名稱是:'|| get_emp_name(7369));
dbms_output.put_line('僱員 7839的名稱是:'|| get_emp_name(7839));
end;

顯示結果爲:
sql代碼
僱員 7369的名稱是:smith
僱員 7839的名稱是:king
pl/sql過程已成功完成。

說明:函數的調用直接出現在程序的 dbms_output.put_line語句中,作爲字符串表達式的一部分。如果輸入了錯誤的僱員編號,就會在函數的錯誤處理部分輸出錯誤信息。試修改僱員編號,重新運行調用部分。

【練習 1】創建一個通過部門編號返回部門名稱的存儲函數 get_dept_name。
【練習 2】將函數的執行權限授予 student賬戶,然後登錄 student賬戶調用。
存儲過程和函數的查看可以通過對數據字典的訪問來查詢存儲過程或函數的有關信息,如果要查詢當前用戶的存儲過程或函數的源代碼,可以通過對user_source數據字典視圖的查詢得到。user_source的結構如下:
sql代碼

describe user_source
結果爲:

sql代碼

名稱          是否爲空?類型
 
name varchar2(30)
type varchar2(12)
line number
text varchar2(4000)

說明:裏面按行存放着過程或函數的腳本,name是過程或函數名,type代表類型(procedure或function),line是行號,text爲腳本。

select text from user_source where name='emp_count';
結果爲:
sql代碼
text

procedure emp_count(p_total out number)
as
begin
select count(*) into p_total from emp;
end;

【訓練 2】查詢過程 get_emp_name的參數。
在 sql*plus中輸入並執行如下查詢:
sql代碼

describe get_emp_name
結果爲:
sql代碼
function get_emp_name returns varchar2

參數名稱    類型        輸入/輸出默認值?
 
-------- ------- --------------------
p_empno  number(4) in default

【訓練 3】在發生編譯錯誤時,顯示錯誤。
sql代碼
show errors
以下是一段編譯錯誤顯示:
sql代碼

---------- -------------------  --------------
4/2 pl/sql: sql statement ignored
4/36     pls-00201:必須說明標識符 'empp'

說明:查詢一個存儲過程或函數是否是有效狀態(即編譯成功),可以使用數據字典 user_objects的status列。

【訓練 4】查詢 emp_list存儲過程是否可用:
sql代碼

elect status from user_objects where object_name='emp_list';

結果爲:
sql代碼
status
------------
valid

說明:valid表示該存儲過程有效(即通過編譯),invalid表示存儲過程無效或需要重新編譯。當 oracle調用一個無效的存儲過程或函數時,首先試圖對其進行編譯,如果編譯成功則將狀態置成 valid並執行,否則給出錯誤信息。當一個存儲過程編譯成功,狀態變爲 valid,會不會在某些情況下變成invalid。結論是完全可能的。比如一個存儲過程中包含對錶的查詢,如果表被修改或刪除,存儲過程就會變成無效 invalid。所以要注意存儲過程和函數對其他對象的依賴關係。如果要檢查存儲過程或函數的依賴性,可以通過查詢數據字典 user_denpendencies來確定,該表結
構如下:
sql代碼

describe user_dependencies;
結果:
sql代碼
名稱
是否爲空
類型
----- ----------    ------------
name   not null      varchar2(30)
type                varchar2(12)
referenced_owner      varchar2(30)
referenced_name       varchar2(64)
referenced_type       varchar2(12)
referenced_link_name  varchar2(128)
schemaid             number
dependency_type       varchar2(4)

說明: name爲實體名, type爲實體類型, referenced_owner爲涉及到的實體擁有者賬戶,referenced_name爲涉及到的實體名,referenced_type爲涉及到的實體類型。
【訓練 5】查詢 emp_list存儲過程的依賴性。
sql代碼

select referenced_name,referenced_type from user_dependencies where name='emp_list';
執行結果:
sql代碼
referenced_name                     referenced_type
------------------------------ ---------------------------
standard                            package
sys_stub_for_purity_analysis        package
dbms_output                         package
dbms_output                         synonym
dbms_output                         non-existent
emp                                 table
emp_count                           procedure

說明:可以看出存儲過程 emp_list依賴一些系統包、emp表和 emp_count存儲過程。如果刪除了 emp表或 emp_count存儲過程,emp_list將變成無效。還有一種情況需要我們注意:如果一個用戶 a被授予執行屬於用戶 b的一個存儲過程的權限,在用戶 b的存儲過程中,訪問到用戶 c的表,用戶 b被授予訪問用戶 c的表的權限,但用戶 a沒有被授予訪問用戶 c表的權限,那麼用戶 a調用
用戶 b的存儲過程是失敗的還是成功的呢?答案是成功的。如果讀者有興趣,不妨進行一下實際測試。

2、程序包
包的概念和組成
包是用來存儲相關程序結構的對象,它存儲於數據字典中。包由兩個分離的部分組成:包頭(package) 和包體(package body)。包頭是包的說明部分,是對外的操作接口,對應用是可見的;包體是包的代碼和實現部分,對應用來說是不可見的黑盒。包中可以包含的程序結構如下所示。

sql代碼
 
過程(procudure)     帶參數的命名的程序模塊
函數(function)      帶參數、具有返回值的命名的程序模塊
變量(variable)      存儲變化的量的存儲單元
常量(constant)      存儲不變的量的存儲單元
遊標(cursor)        用戶定義的數據操作緩存區,在可執行部分使用
類型(type)          用戶定義的新的結構類型
異常(exception)     在標準包中定義或由用戶自定義,用於處理程序錯誤

說明部分可以出現在包的三個不同的部分:出現在包頭中的稱爲公有元素,出現在包體中的稱爲私有元素,出現在包體的過程(或函數)中的稱爲局部變量。它們的性質有所不同,如下所示。

sql代碼

公有元素(public)
過程有效

在包頭中說明,在包體中具體定義在包外可見並可以訪問,對整個應用的全

私有元素(private)

在包體的說明部分說明

只能被包內部的其他部分訪問

局部變量(local)在過程或函數的說明部分說明

只能在定義變量的過程或函數中使用

在包體中出現的過程或函數,如果需要對外公用,就必須在包頭中說明,包頭中的說明應該和包體
中的說明一致。
包有以下優點:
*包可以方便地將存儲過程和函數組織到一起,每個包又是相互獨立的。在不同的包中,過程、函數都可以重名,這解決了在同一個用戶環境中命名的衝突問題。
*包增強了對存儲過程和函數的安全管理,對整個包的訪問權只需一次授予。
*在同一個會話中,公用變量的值將被保留,直到會話結束。
*區分了公有過程和私有過程,包體的私有過程增加了過程和函數的保密性。
*包在被首次調用時,就作爲一個整體被全部調入內存,減少了多次訪問過程或函數的 i/o次數。創建包和包體
包由包頭和包體兩部分組成,包的創建應該先創建包頭部分,然後創建包體部分。創建、刪除和編譯包的權限同創建、刪除和編譯存儲過程的權限相同。
創建包頭的簡要語句如下:

create [or replace] package包名
{is|as}
公有變量定義
公有類型定義
公有遊標定義
公有異常定義
函數說明
過程說明
end;

創建包體的簡要語法如下:

create [or replace] package body包名
{is|as}
私有變量定義
私有類型定義
私有遊標定義
私有異常定義
函數定義
過程定義
end;

包的其他操作命令包括:

刪除包頭:
drop package 包頭名
刪除包體:
drop package body 包體名
重新編譯包頭:
alter package 包名 compile package
重新編譯包體:
alter package 包名 compile package body

在包頭中說明的對象可以在包外調用,調用的方法和調用單獨的過程或函數的方法基本相同,惟一的區別就是要在調用的過程或函數名前加上包的名字(中間用“.”分隔)。但要注意,不同的會話將單獨對包的公用變量進行初始化,所以不同的會話對包的調用屬於不同的應用。系統包 oracle預定義了很多標準的系統包,這些包可以在應用中直接使用,比如在訓練中我們使用的dbms_output包,就是系統包。put_line是該包的一個函數。常用系統包下所示。

sql代碼
dbms_output在 sql*plus環境下輸出信息
 
dbms_ddl  編譯過程函數和包
dbms_session   改變用戶的會話,初始化包等
 dbms_transaction  控制數據庫事務
 

 
dbms_mail   連接 oracle*mail
dbms_lock   進行復雜的鎖機制管理
dbms_alert  識別數據庫事件告警
dbms_pipe   通過管道在會話間傳遞信息
dbms_job    管理 oracle的作業
dbms_lob    操縱大對象
dbms_sql    執行動態 sql語句
 
dbms_output在 sql*plus環境下輸出信息
 
dbms_ddl      編譯過程函數和包
dbms_session  改變用戶的會話,初始化包等
dbms_transaction  控制數據庫事務
 
dbms_mail   連接 oracle*mail
dbms_lock   進行復雜的鎖機制管理
dbms_alert  識別數據庫事件告警
dbms_pipe   通過管道在會話間傳遞信息 


dbms_job  管理 oracle的作業
dbms_lob  操縱大對象
dbms_sql  執行動態 sql語句

包的應用
在 sql*plus環境下,包和包體可以分別編譯,也可以一起編譯。如果分別編譯,則要先編譯包頭,後編譯包體。如果在一起編譯,則包頭寫在前,包體在後,中間用“/”分隔。
可以將已經存在的存儲過程或函數添加到包中,方法是去掉過程或函數創建語句的 create or replace部分,將存儲過程或函數複製到包體中,然後重新編譯即可。
如果需要將私有過程或函數變成共有過程或函數的話,將過程或函數說明部分複製到包頭說明部分,然後重新編譯就可以了。

發佈了61 篇原創文章 · 獲贊 92 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章