通常來講過程和函數被稱爲子程序。過程是一段不具備返回值的代碼塊,而函數會返回一個值。子程序與匿名塊的最大不一樣是它們能夠存儲到數據庫的字典中,以便重用。程序員
向dept表插入記錄的過程算法
create or replace procedure newdept(sql
p_deptno dept.deptno%TYPE,數據庫
p_dname dept.dname%TYPE,編程
p_loc dept.loc%TYPE服務器
)oracle
ASapp
v_deptcount NUMBER;編程語言
beginide
select count(*) into v_deptcount from dept where deptno=p_deptno;
if v_deptcount>0
then
raise_application_error(-20002,'出現了相同的員工記錄');
end if;
insert into dept(deptno,dname,loc) values(p_deptno,p_dname,p_loc);
commit;
end newdept;
調用上面這個過程
begin
newdept(10,'成本科','深圳');
exception
when others then
dbms_output.put_line('產生了錯誤:'||SQLERRM);
end;
子程序的優勢
提供模塊化功能:模塊化是將一個大的代碼塊打散爲多個小的易於管理的子程序,由其餘模塊調用,使得代碼具備更強的可讀性和可維護性。
更強的可管理型:大多數程序員都不肯意看到一個超過1000行的語句塊這種寫法,由於管理起來至關困難,特別是在後期維護時,若是使用子程序,則能夠將這1000行代碼打散,提供各個子程序進行調用,既方便調試,又提供了較強的可管理性
加強的可讀性:每一個子程序都具備描述性的命名,使得程序的閱讀者可以很容易地瞭解子程序的功能,進而容易理解和把握整個程序,子程序使得閱讀代碼的人首先看到一我的的實現結構,而不用一開始就關注到具體的可執行語句的細節
更強的穩定性:子程序便於調試,使得代碼具備較少的錯誤。
create or replace procedure newdept(
p_deptno IN number,
p_dname IN varchar2,
p_loc IN varchar2
)
AS
v_deptcount number(4);
e_duplication_dept exception;
begin
select count(*) into v_deptcount from dept
where deptno=p_deptno;
if v_deptcount>0
then
raise e_duplication_dept;
end if;
insert into dept(deptno,dname,loc) values (p_deptno,p_dname,p_loc);
commit;
exception
when e_duplication_dept then
rollback;
raise_application_error(-20002,'出現了相同的員工記錄');
end newdept;
能夠看到,在爲過程傳遞參數時,參數名稱統一以p開頭,這只是一種約定,並非原則,IN關鍵字用來指明參數爲輸入參數,參數的類型並無指定長度:AS以後的語句是局部定義區,在示例中定義了一個變量和異常,這相似於匿名塊的Declare區域;begin以後是過程的代碼執行區,當員工編號重複時,將觸發異常;exception捕獲了這個異常,使用RAISE_APPLICATION_ERROR向調用方傳遞友好的錯誤消息。
函數體內部,包含了多個return語句用來將函數的值返回給調用環境。
一個函數體內能夠有多個return語句,但只有一個return語句會被執行,當執行到return語句時,函數將再也不往下執行,控制會當即返回到調用函數的環境中。
create or replace function getraisedsalary(p_empno emp.empno%TYPE)
return number
is
v_job emp.job%TYPE;
v_sal emp.sal%TYPE;
v_salaryratio number(10,2);
begin
select job,sal into v_job,v_sal from emp where empno=p_empno;
case v_job
when '職員' then
v_salaryratio:=1.09;
when '銷售人員' then
v_salaryratio:=1.11;
when '經理' then
v_salaryratio:=1.18;
else
v_salaryratio:=1;
end case;
if v_salaryratio<>1
then
return round(v_sal * v_salaryratio,2);
else
return v_sal;
end if;
exception
when no_data_found then
return 0;
end getraisedsalary;
調用函數
declare
v_raisedsal number(10,2);
begin
dbms_output.put_line('7369員工調薪記錄:'||getraisedsalary(7369));
v_raisedsal:=getraisedsalary(7521);
dbms_output.put_line('7521員工調薪記錄:'||getraisedsalary(7521));
end;
在過程當中return語句不返回值,也不返回任何表達式,它的做用是當即退出過程的執行,將控制權返回給過程的調用者。
在函數中return語句必須包含一個表達式,表達式的值會在return語句執行時被計算,而後賦給在聲明中的return語句中指定的數據類型的變量,也就是函數標識符,再將控制權返回給調用者。
create or replace procedure raisesalary(
p_empno emp.empno%TYPE
)
AS
v_job emp.job%TYPE;
v_sal emp.sal%TYPE;
begin
select job,sal into v_job,v_sal from emp where empno=p_empno;
if v_job<>'職員' then
return;
elsif v_sal>3000 then
return;
else
update emp set sal=round(sal*1.12,2) where empno=p_empno;
end if;
exception
when no_data_found then
dbms_output.put_line('沒有找到員工記錄');
end raisesalary;
在產生了錯誤後,能夠經過user_errors將全部的錯誤都顯示出來。
select line,position,text from user_errors where name='RAISESALARY' order by sequence;
形參與實參
形式參數:在定義子程序時,在定義語句中定義的參數稱爲形式參數。簡稱形參
實際參數:在調用子程序時,傳入的具體參數值稱爲實際參數,簡稱實參。
子程序在定義過程當中定義的參數及在過程體中使用的參數都是形式參數,這些參數不具備實際的值,僅是過程須要的數據的佔位符。
create or replace procedure insertdept(
p_deptno number, --形參
p_dname varchar2,
p_loc varchar2
)
AS
v_count number(10);
begin
select count(deptno) into v_count from dept where deptno=p_deptno;
if v_count>1 then
raise_application_error(-20001,'數據庫中存在相同名稱的部門編號');
end if;
insert into dept values(p_deptno,p_dname,p_loc);
commit;
end insertdept;
調用時
insertdept(55,'行政部','德克薩斯'); 實參
參數模式
形式參數的模式用來控制形式參數的行爲,通常有3中類型的模式:IN OUT 和IN OUT 若是沒有指定參數的模式 默認爲IN模式
1.IN模式
IN模式的參數稱爲輸入參數,這是默認的參數模式。IN模式直接把值傳遞給調用子程序,IN模式的參數就像常量同樣,不能被賦值,能夠爲IN模式的參數初始化一個默認值。
create or replace procedure insertdept(
p_deptno IN number:=55, --形參 並賦初值
p_dname IN varchar2,
p_loc IN varchar2
)
AS
v_count number(10);
begin
--p_dname:='市場策略部'; --錯誤 不能對IN模式參數進行賦值
select count(deptno) into v_count from dept where deptno=p_deptno;
if v_count>1 then
raise_application_error(-20001,'數據庫中存在相同名稱的部門編號');
end if;
insert into dept values(p_deptno,p_dname,p_loc); --在過程體中使用形式參數
commit;
end insertdept;
調用
begin
insertdept(55,'勤運部','西北');
end;
2.OUT模式
OUT模式的參數又稱爲輸出參數,輸出參數將會改變參數的值,所以實際參數不能用文字或常量來表示,必需要先定義一個變量,而後將該變量做爲一個實際參數使用來調用過程。
create or replace procedure outraisesalary(
p_empno IN number, --定義一個員工加薪後的薪資的輸出變量
p_raisedsalary OUT number
)
AS
v_sal number(10,2); --定義本地局部變量
v_job varchar2(10);
begin
p_raisedsalary:=0;
select sal,job into v_sal,v_job from emp where empno=p_empno; --查詢員工信息
if v_job='職員' then
p_raisedsalary:=v_sal * 1.12; --對OUT模式的參數進行賦值是合法的
update emp set sal=p_raisesalary where empno=p_empno;
else
p_raisesalary:=v_sal; --不然賦原來的薪資值
end if;
exception
when no_data_found then --異常處理語句塊
dbms_output.put_line('沒有找到該員工的記錄');
end outraisesalary;
調用
declare
v_raisedsalary number(10,2); --定義一個變量保存輸出值
begin
v_raisedsalary:=100; --這個賦值在傳入到outraisesalary後被忽略
outraisesalary(7369,v_raisedsalary); --調用函數
dbms_output.put_line(v_raisedsalary); --顯示輸出參數的值
end;
v_raisedsalary這個變量用來傳給outraisesalary過程當中的輸出參數做爲實際參數,儘管在過程體中爲該變量賦了初值,可是當調用outraisesalary時,該變量的任何初始值都會被忽略。
OUT模式的形式參數會被初始化爲NULL,因此形參的數據類型是不能有NOT NULL約束的,好比內置類型NATURALN和POSITIVEN,不然PL/SQL會拋出VALUE_ERROR異常
3.IN OUT模式
IN OUT模式是IN和OUT方式的組合,又稱爲輸入/輸出參數,當過程被調用時,實際參數的值被傳遞給過程,形式參數能夠被讀出和寫入,當過程結束,控制返回到調用環境時,形式參數的內容被賦給實際參數。在過程內部,輸入/輸出參數就像是一個初始化了的變量,能夠從變量中讀取值,也能夠爲其賦值而產生輸出。IN OUT 模式示例:
create or replace procedure calcraisedsalary(
p_job IN varchar2,
p_salary IN OUT number --定義輸出/輸入參數
)
AS
v_sal number(10,2); --保存調整後的薪資值
begin
if p_job='職員' then --根據不一樣的job進行薪資的調整
v_sal:=p_salary * 1.12;
elsif p_job='銷售人員' then
v_sal:=p_salary * 1.18;
elsif p_job='經理' then
v_sal:=p_salary * 1.19
else
v_sal:=p_salary;
end if;
p_salary:=v_sal; --將調整後的結果賦給輸入/輸出參數
end calcraisedsalary;
調用
declare
v_sal number(10,2); --薪資變量
v_job varchar2(10); --職位變動
begin
select sal,job into v_sal,v_job from emp where empno=7369; --獲取薪資和職位信息
calcraisedsalary(v_job,v_sal); --計算調薪
dbms_output.put_line('計算後的調整薪水爲:'|| v_sal); --獲取調薪後的結果
end;
形式參數的約束
在過程被調用時,將傳入實際參數的值,在過程定義時,形式參數不能指定長度的約束,任何指定長度或精度來約束都是不合法的。
形式參數不能用約束聲明,可是可使用%TYPE對其進行約束。
create or replace procedure calcraisedsalarywithtype(
p_job IN emp.job%TYPE
)
要是改爲p_job IN varchar2(10) 就是錯的 不能加長度 或精度 約束
只有在
declare
v_sal number(10,2);
begin
calcraisedsalarywithtype(v_sal);
end;
參數傳遞方式
在調用子程序時,有兩種向子程序的形式參數傳遞實際參數的方式:一種是前面見過的按位置傳遞;另外一種是按名稱傳遞。
大多數參數傳遞的場合都使用按位置傳遞方式,只要傳入的實際參數的位置匹配形式參數的位置定義便可。例如過程接收2個參數
calcraisesalary(v_job,v_sal);
還可使用相似的按名稱傳遞方法,這種方法將使用=>做爲關聯的操做符,把左邊的實參和右邊的形參關聯起來,所以上述調用也能夠寫爲以下形式:
calcraisesalary(p_job=>v_job,p_salary=>v_sal);
能夠看到,p_job與p_salary是在過程定義中使用的形式參數,而v_sal與v_job是實際參數,因爲使用了名字表示法,所以參數的位置就顯得不那麼重要了,所以以下的調用也是合法的:
calcraisesalary(p_job=>v_job,p_salary=>v_sal);
還能夠在過程調用中混合使用按位置傳遞與按名稱傳遞兩種方式,可是在這種狀況下,位置標示法必須在名字標示法以前,不能反過來使用。
calcraisesalary(v_job,p_salary=>v_sal);
若是反過來,將名稱調用法放在前面,則是非法的
calcraisesalary(p_salary=>v_sal,v_job);
參數默認值
在定義子程序時,可使用default關鍵字或賦值語句爲IN模式的參數指定默認值,在調用子程序時能夠根據須要傳遞不一樣個數的參數。
create or replace procedure newdeptwithdefault(
p_deptno dept.deptno%TYPE default 57,
p_dname dept.dname%TYPE:='管理部',
p_loc dept.loc%TYPE default '江蘇'
)
AS
v_deptcount number;
begin
select count(*) into v_deptcount from dept where deptno=p_deptno;
if v_deptcount>0
then
raise_application_error(-20002,'出現了相同的員工記錄');
end if;
insert into dept(deptno,dname,loc) values(p_deptno,p_dname,p_loc);
end;
調用方法
begin
newdeptwithdefault; --不指定任何參數,將使用形參默認值
end;
begin
newdeptwithdefault(58,'事務組'); ---讓loc參數使用默認值
end;
begin
newdeptwithdefault(p_deptno=>58,p_loc=>'南海'); --讓dname使用默認值
end;
使用NOCOPY編譯提示
值傳遞:當參數經過值傳遞時,參數將從實際參數中被複制形式參數中。
引用傳遞:實際參數的指針被傳遞到了相應的形式參數中。
當要在過程定義中存在NOCOPY時,PLSQL編譯器將經過引用傳遞參數,可是因爲NOCOPY只是一個編譯器提示,而不是一個指令,所以並不必定會使用引用傳遞,可是多數狀況下是可行的。
create or replace procedure nocopydemo
(
p_inparameter in number,
p_inoutparameter in out nocopy varchar2, --使用NOCOPY編譯提示
p_outparameter out nocopy varchar2
)
IS
begin
NULL;
end;
NOCOPY一般用在out和in out這類按值傳遞的形式參數中,而且是參數佔用大量內存的場合,以免複製數據帶來的性能開銷。
declare
TYPE emptabtyp IS table of emp%ROWTYPE; --定義嵌套表類型
emp_tab emptabtyp:=emptabtyp(NULL); --定義一個空白的嵌套表變量
t1 number(5);
t2 number(5);
t3 number(5);
procedure get_time(t out number) --獲取當前時間
IS
begin
select to_char(SYSDATE,'SSSSS') into t from dual;
end;
procedure do_nothing1(tab in out emptabtyp)
IS
begin
NULL;
end;
procedure do_nothing2(tab in out NOCOPY emptabtyp)
IS
begin
NULL;
end;
begin
select * into emp_tab(1) from emp where empno=7788;
emp_tab.EXTEND(900000,1);
get_time(t1);
do_nothing1(emp_tab);
get_time(t2);
do_nothing2(emp_tab);
get_time(t3);
dbms_output.put_line('調用所花費的時間秒');
dbms_output.put_line('------------------');
dbms_output.put_line('不帶NOCOPY的調用:'||TO_CHAR(t2-t1));
dbms_output.put_line('帶NOCOPY的調用:'||TO_CHAR(t3-t2));
end;
在SQL中調用子程序
1.全部函數的參數必須是IN模式,IN OUT 和OUT模式的參數是不能被SQL語句使用的
2.函數參數的數據類型和RETURN子句的返回類型,必須能被oracle數據庫識別,這是由於PL/SQL兼容全部的oracle數據類型,可是PL/SQL擴充了本身的類型,好比BOOLEAN,INTEGER,記錄,集合和程序員定義的子類型等
3.函數必須被存儲在數據庫中,在客戶端PL/SQL環境中定義的PL/SQL函數是不能被SQL語句調用獲得的
除了這些規則以外,在SQL中調用PL/SQL自定義的函數還具備以下的約束。
函數不能修改數據庫表,它不能執行任何下面的語句:DDL語句,好比CREATE TABLE,DROP INDEX等,不能在函數中使用COMMIT或ROLLBACK提交或回滾事務,當函數定義在自治事務中時,這個限制稍稍寬鬆一些。由於在自治事務中會與調用事務獨立出來。
自治事務
1.當調用遠程的函數或經過並行行爲調用其餘會話中的函數時,函數可能不能讀取或寫入包變量的值,由於oracle服務器不支持跨用戶會話訪問。
2.僅當函數在一個select列表中被調用時,或者是values或set子句中,函數纔可以更新包變量的值,若是在where或group by子句中,它可能沒法改寫包變量的值
3.在oracle8i以前的版本中,不能在用戶自定義函數中調用RAISE_APPLICATION_ERROR拋出異常。
4.函數不能調用其餘模塊(好比說存儲過程或函數),不然將打斷任何先前定義的規則
5.函數不能引用一個視圖,視圖也就是存儲了select語句的查詢
create or replace function getempdept(
p_empno emp.empno%TYPE
)RETURN VARCHAR2
AS
v_dname dept.dname%TYPE;
begin
select b.dname into v_dname from emp a,dept b where a.deptno=b.deptno and a.empno=p_empno;
return v_dname;
exception
when no_data_found then
return null;
end;
嵌套子程序
內嵌子程序是一個過程或函數,它定義在PL/SQL塊的聲明區中(能夠是命名塊或匿名塊),定義在塊的聲明區中的子程序僅能被這個塊調用,不能被任何定義在塊外部的子程序或塊調用,嵌套子程序與其外部塊的結構,嵌套子程序的做用域只能位於其定義的塊自己,不能被外部塊調用。在語句塊中使用嵌套子程序有以下幾個好處
1.經過提取重複代碼到嵌套子程序中,能夠減少外部塊的代碼大小。
2.能夠提高代碼的可讀性
create or replace function getraisedsalary_subprogram(p_empno emp.empno%TYPE)
return number
is
v_salaryratio number(10,2);
v_sal emp.sal%TYPE;
function getratio(p_sal out number) return number is
n_job emp.job%TYPE;
n_salaryratio number(10,2);
begin
select job,sal into n_job,p_sal from emp where empno=p_empno;
case n_job
when '職員' then
n_salaryratio:=1.09;
when '銷售人員' then
n_salaryratio:=1.11;
when '經理' then
n_salaryratio:=1.18;
else
n_salaryratio:=1;
end case;
return n_salaryratio;
end;
begin
v_salaryratio:=getratio(v_sal);
if v_salaryratio <> 1
then
return round(v_sal * v_salaryratio,2);
else
return v_sal;
end if;
exception
when no_data_found then
return 0;
end;
嵌套子程序僅能定義在變量聲明語句的裏面,不然會報錯,子程序不須要單獨存儲在數據字典中
調用
begin
dbms_output.put_line('7369員工調薪記錄:'||getraisedsalary_subprogram(7369));
dbms_output.put_line('7521員工調薪記錄:'||getraisedsalary_subprogram(7521));
end;
嵌套子程序與存儲子程序的異同
存儲子程序
1.子程序以編譯的形式存儲在數據字典中,當調用過程時,不須要從新編譯
2.子程序能夠從對該子程序具備EXECUTE權限的用戶所提交的任何語句塊中調用
3.經過將子程序代碼與調用塊分開,使調用塊更短,更容易理解和維護,若是願意,子程序和調用塊還能夠分開來進行維護
4.可使用dbms_shared_pool.keep包過程把已編譯僞代碼鎖定在共享池中以便重用,這樣能夠改進其性能。
5.獨立的存儲子程序不能重載,可是包中的子程序能夠在同一個包中重載
嵌套子程序
1.嵌套子程序被編譯爲包含它的語句塊的一部分,若是包含它的語句塊是匿名的,並屢次運行,那麼每次都必須編譯子程序
2.嵌套子程序只能從包含子程序的語句塊中調用
3.子程序和調用塊是徹底相同的,這會致使混亂,若是對調用塊進行了更改,那麼子程序也將被編譯爲包含它的塊的重編譯塊的一部分
4.嵌套子程序不能被其餘子程序鎖定在共享池中
5.嵌套子程序能夠在同一個語句塊中重載
子程序的前向聲明
PL/SQL支持遞歸調用,所以兩個或多個子程序能夠互相調用對象,嵌套子程序的互調。
declare
v_val binary_integer:=5;
procedure a(p_counter in out binary_integer) is
begin
dbms_output.put_line('A('||p_counter||')');
if p_counter>0 then
b(p_counter);
p_counter:=p_counter-1;
end if;
end a;
procedure b(p_counter in out binary_integer) is
begin
dbms_output.put_line('b('||p_counter||')');
p_counter:=p_counter-1;
a(p_counter);
end b;
begin
b(v_val);
end;
上面代碼會產生異常, 在此做用域沒有聲明b的異常,此時可使用前向聲明(或稱預聲明),前向聲明僅包含子程序的結構定義,並不包含具體的實現代碼,這種聲明也用於包中的包頭中。
declare
v_val binary_integer:=5;
procedure b(p_counter in out binary_integer);
procedure a(p_counter in out binary_integer) is
begin
dbms_output.put_line('a(’||p_counter||')');
if p_counter>0 then
b(p_counter);
p_counter:=p_counter-1;
end if;
end a;
procedure b(p_counter in out binary_integer) is
begin
dbms_output.put_line('b('||p_counter||')');
p_counter:=p_counter-1;
a(p_counter);
end b;
begin
b(v_val);
end;
重載子程序
重載是面向對象的編程語言中很是常見的一種編寫對象方法的方式,重載是指具備相同名稱的方法,可是在參數的類型或順序或是數據類型上有所不一樣。在PLSQL的包中能夠編寫重載特性的子程序。
在PLSQL塊中嵌套子程序重載的原則與包或對象的重載類似,重載的子程序具備相同的名稱,可是參數的類型,順序或數據類型不一樣。
declare
procedure getsalary(p_empno IN number) is --帶一個參數的過程
begin
dbms_output.put_line('員工編號爲:'||p_empno);
end;
procedure getsalary(p_empname IN varchar2) is --重載的過程
begin
dbms_output.put_line('員工名稱爲:'||p_empname);
end;
procedure getsalary(p_empno in number,p_empname in varchar) is
begin
dbms_output.put_line('員工編號爲:'||p_empno||'員工名稱爲:'||p_empname);
end;
begin
getsalary(7369); --調用重載方法
getsalary('史密斯');
getsalary(7369,'史密斯');
end;
子程序自治事務
當進行子程序開發時,若是想獨立於主事務開始一個獨立的事務,在子程序中使用COMMIT或ROLLBACK語句時,不影響主事務的狀態,這種事務稱爲自治事務
自治事務是由主事務開啓的獨立事務,自治事務把主事務掛起來,而後執行SQL操做,在提交或回滾這些操做後,從新恢復主事務。自治事務與主事務的關係。
自治事務使用AUTONOMOUS_TRANSACTION編譯提示來定義,這個編譯提示會讓PLSQL編譯器把子程序或數據庫觸發器標記爲自治的事務。能夠將這個指令放到程序聲明部分的任何地方,可是爲了良好的可讀性,通常把它放到聲明區的頂部,基本語法以下:
PRAGMA AUTONOMOUS_TRANSACTION;
declare
procedure testautonomous(p_empno number) as
PRAGMA AUTONOMOUS_TRANSACTION; --標記爲自治事務
begin
insert into emp_history select * from emp where empno=p_empno;
commit;
end testautonomous;
begin
insert into emp_history(empno,ename,sal) values(1011,'測試',1000);
testautonomous(7369);
rollback
end;
遞歸調用子程序
遞歸是一個很是重要並且在平常工做中使用很是頻繁的算法,它經過不斷地調用自身來實現層次化的處理工做。
遞歸算法中具備以下兩個規則。
1.必需要有一個方法可以退出遞歸循環,以避免永遠地遞歸下去。若是遞歸程序無限制地執行下去,PL/SQL最終會用光內存然互拋出預約義的STORAGE_ERROR異常.
2.要有一個方法調用自身,經過不斷地改變條件來使得遞歸接近退出的位置。
遞歸階乘
declare
v_result integer;
function fac(n positive)
return integer is
begin
if n=1 then
dbms_output.put('1!=1*0!');
return 1;
else
dbms_output.put(n||'!='||n||'*');
return n*fac(n-1);
end if;
end fac;
begin
v_result:=fac(10);
dbms_output.put_line('結果是:'||v_result);
end;
使用遞歸查找職員列表示例
declare
procedure find_staff(mgr_no number,tier number:=1)
is
boss_name varchar2(10);
cursor c1 (boss_no number)
is
select empno,ename from emp where mgr=boss_no;
begin
select ename into boss_name from emp
where empno=mgr_no;
if tier=1
then
insert into staff values(boss_name||'是老闆');
end if;
for ee in c1 (mgr_no)
loop
insert into staff values (boss_name
||'管理'
||ee.ename
||'在層次'
||TO_CHAR(tier));
find_staff(ee.empno,tier+1);
end loop;
commit;
end find_staff;
begin
find_staff(7839);
end;
理解子程序依賴性
在建立子程序時,每每須要引用到其餘的對象,好比過程insertdept須要更新dept表,那麼能夠將過程insertdept稱爲對dept表的對象依賴,而將表dept稱爲被引用對象。其中對象依賴又包含了兩種狀況:直接依賴和間接依賴。
子程序依賴示例
create or replace procedure testdependence as
begin
insert into emp(empno,ename,sal) values(1011,'測試',1000);
testsubprog(7369);
rollback;
end;
被另外一個程序調用,用來向表emp_history表插入數據
create or replace procedure testsubprog(p_empno number)as
begin
insert into emp_history select * from emp where empno=p_empno;
end testsubprog;
查看依賴
對於直接依賴
select name,type from user_dependencies where referenced_name='EMP';
查看間接依賴性
1.首先執行一下 ADMIN\utldtree.sql
2.EXEC deptree_fill('TABLE','SCOTT','EMP');
3.select nested_level,name,type from deptree where type in('PROCEDURE','FUNCTION');
nested_level是依賴的層次數據,若是是1則表示爲直接依賴,若是是2則表示爲間接依賴。
查看對象有效性
當對字程序直接或間接依賴的對象進行修改以後,好比DDL 那麼存儲子程序就可能變得無效
1.alter table emp_history add emp_desc varchar2(200) NULL;
2.select object_name,object_type,status from user_objects where object_name in('TESTDEPENDENCE','TESTSUBPROG');
從新編譯
若是一個依賴對象失效,試圖下一次調用時從新編譯,但並非都有效的。
1.alter table emp_history drop column emp_desc;
2.alter procedure testdependence compile;
3.alter procedure testsubprog compile;
4.select object_name,boject_type,status from user_objects where object_name in ('TESTDEPENDENCE','TESTSUBPROG');
子程序權限管理
其餘用戶調用scott的
grant execute on find_staff to userb;
begin
scott.find_staff(7839);
end;
也可使用同義詞