oracle學習總結------procedure
阿新 • • 發佈:2019-01-07
--子程式(儲存過程,函式)
--儲存過程
--語法:
--create or replace procedure 儲存過程名字【(引數列)】
--is|as
--宣告區
--begin
--執行區
--exception
--異常處理
--end;
--儲存過程的引數分為三類 in, out, in out 引數型別不能帶長度
--in是將實際引數傳給形參,預設型別
--out是將形式引數傳遞給實參,可以實現多個值得返回
-- in out 兩個兼備
--例項:建立一個儲存過程,列印所有部門的編號和部門的平均工資
create or replace procedure pro_get_sal is
v_deptno emp.deptno%type;
v_avg_sal emp.sal%type;
cursor cur is select deptno,avg(nvl(sal,0)) from emp group by deptno;
begin
open cur;
fetch cur into v_deptno,v_avg_sal;
while cur%found loop
dbms_output.put_line('deptno=' || v_deptno ||'v_avg_sal=' || v_avg_sal);
fetch cur into v_deptno,v_avg_sal;
end loop;
close cur;
end;
--例項:建立一個儲存過程,列印所有部門的編號和部門的平均工資
create or replace procedure pro_get_sal2 is
begin
for emp in(select deptno,avg(nvl(sal,0)) avg_sal from emp group by deptno) loop
dbms_output.put_line('deptno=' || emp.deptno ||'v_avg_sal=' || emp.avg_sal);
end loop;
end;
declare
begin
pro_get_sal2();
end;
--建立一個儲存過程,引數傳入一個員工編號,列印該員工所在的職位的員工姓名和薪資
create or replace procedure get_jon_empty(eno in emp.empno%type)
is
begin
for e in ( select * from emp where job like(select job from emp where empno=eno) )loop
dbms_output.put_line(e.ename || ' ' || e.sal || ' ' || e.job);
end loop;
end;
--呼叫儲存過程
declare
begin
--pro_get_sal;
get_jon_empty('&input');
end;
--刪除儲存過程
drop procedure pro_get_sal;
--查詢CLERK的所有員工資訊
select * from(select * from emp where job='&input');
--建立一個儲存過程,引數傳入一個員工編號,列印該員工所在的職位的員工姓名和薪資
declare
begin
for e in ( select * from emp where job like(select job from emp where empno='&input') )loop
dbms_output.put_line(e.ename || ' ' || e.sal);
end loop;
end;
--建立一個儲存過程,引數傳入部門編號,輸出該部門的平均工資。
create or replace procedure get_dept_sal(dno in emp.deptno%type,avg_sal out emp.sal%type)
is
begin
select avg(nvl(sal,0)) into avg_sal from emp where deptno = dno;
end;
declare
s emp.sal %type;
begin
get_dept_sal('&input',s);
dbms_output.put_line(s);
end;
--建立一個儲存過程,引數傳入一個員工編號,輸出該員工的姓名,
--薪資,職位,用該職位作為引數建立儲存過程,用於查詢該職位的員工資訊
--建立一個儲存過程,引數傳入一個員工編號,輸出該員工的姓名,薪資,職位,
create or replace procedure get_emp_info(eno in emp.empno%type,
v_name out emp.ename%type,v_sal out emp.sal%type,v_job out emp.job%type)
as
begin
select ename,sal,job into v_name,v_sal,v_job from emp where empno = eno;
end;
--建立一個儲存過程,用於引數傳入則職位,顯示該職位的所有員工資訊
create or replace procedure prin_dept_info(v_job in emp.job%type)
as
begin
for temp in( select * from emp where job = v_job) loop
dbms_output.put_line(temp.empno || ' ' || temp.ename || ' ' ||temp.job ||' '
||to_char(temp.hiredate,'YYYY-MM-DD'));
end loop;
end;
--建立一個儲存過程,用於引數傳入員工編號,和修改的薪資,修改emp的對應引數的員工的薪資
create or replace procedure pro_setSal(in_empno in emp.empno%type,in_sal in emp.sal%type)
is
begin
update emp set sal = in_sal where empno = in_empno;
exception
when no_data_found then
dbms_output.put_line('沒有該員工資訊');
end;
--建立匿名塊,呼叫儲存過程
declare
begin
pro_setSal(7369,1000);
end;
update emp set sal = 500 where empno =7369;
s+
rollback;
declare
v_name emp.ename%type;
v_sal emp.sal%type;
v_job emp.job%type;
begin
get_emp_info('&input',v_name ,v_sal,v_job);
dbms_output.put_line(v_name || ' ' || v_sal || ' ' ||v_job);
dbms_output.put_line('-----------------');
prin_dept_info(v_job);
end;
--函式
--基本語法
--create or replace function 函式名【(引數列)】
-- return 返回值型別 //返回值型別不能帶長度
-- is|as
--宣告區
--begin
--執行區,一定要有return語句
--exceprion
--異常區
--end;
-- in out 引數
--CASE 條件表示式
--WHEN 條件表示式結果1 THEN
-- 語句段1
--WHEN 條件表示式結果2 THEN
-- 語句段2
--......
--WHEN 條件表示式結果n THEN
-- 語句段n
--[ELSE 條件表示式結果]
--END;
---------格式二---------
--CASE
--WHEN 條件表示式1 THEN
-- 語句段1
--WHEN 條件表示式2 THEN
-- 語句段2
--......
--WHEN 條件表示式n THEN
-- 語句段n
--[ELSE 語句段]
--END;
--例項:引數傳入兩個數,引數輸出他們的四則運算結構
create or replace function operation(num1 number ,num2 number ,c char)
return number
is
re number;
begin
case c
when '+' then
re := num1 + num2;
when '-' then
re := num1 - num2;
when '*' then
re := num1 * num2;
when '/' then
re := num1/num2;
dbms_output.put_line('re-->' + re);
end case ;
return re;
end;
declare
begin
dbms_output.put_line(operation(3 ,5 ,'*'));
end;
--案例:編寫一個函式,用於接收使用者名稱,和返回使用者的年薪
create or replace function fun_annual_salary(v_in_empno number)
return number is
annual_sal number;
begin
select (sal + nvl(comm,0))*13 as an_sal into annual_sal from emp where empno = v_in_empno;
return annual_sal;
exception
when no_data_found then
dbms_output.put_line('沒有該員工!');
end;
declare
an_sal emp.sal%type;
begin
an_sal := fun_annual_salary(7369);
dbms_output.put_line('年薪' || an_sal);
end;
--綜合例項,建立一個包,用於封裝儲存過程和函式,儲存過程用於修改員工的工資,函式用於獲得該員工的工資。
--定義包頭,用於宣告儲存過程和函式
create or replace package pak is
procedure pro(v_in_ename in varchar2,v_in_sal in number);
function fun(v_in_ename in varchar2) return number;
end;
--定義包體,用於定義儲存過程和函式
create or replace package body pak is
--定義儲存過程
procedure pro(v_in_ename in varchar2,v_in_sal in number)
is
begin
update emp set sal = v_in_sal where ename = v_in_ename;
end;
--定義函式
function fun(v_in_ename in varchar2) return number
is
v_sal number;
begin
select sal into v_sal from emp where ename = v_in_ename;
return v_sal;
end;
end;
declare
v_sal number;
begin
select pak.fun('KING') into v_sal FROM dual;
dbms_output.put_line(v_sal);
end;
--例項:建立一個儲存過程,用於引數輸入員工編號,引數輸出員工姓名和薪資,
create or replace procedure proNameSal(v_in_empno in number , v_out_name out varchar2,v_out_sal out number)
is
begin
select ename,sal into v_out_name,v_out_sal from emp where empno = v_in_empno;
end;
--建立一個匿名塊,用於呼叫儲存過程
declare
v_ename emp.ename%type;
v_sal number;
begin
proNameSal(7839,v_ename,v_sal);
dbms_output.put_line('name-->' ||v_ename || 'sal--->' || v_sal );
end;
--建立一個儲存過程,用於引數輸如部門編號,引數輸出該部門的所有員工資訊。
--1,定義一個包,用於定義一個遊標型別
create or replace package pack_cursor is
--定義一個動態遊標資料型別
type dept_corsor is ref cursor;
end;
--2.定義一個儲存,用於引數輸如部門編號,引數輸出該部門的所有員工資訊。
create or replace procedure pro_cursor(v_in_deptno in number,v_out_cursor out pack_cursor.dept_corsor)
is
--自定義異常
nodata exception;
begin
--開啟動態遊標
open v_out_cursor for select empno,ename,sal,deptno from emp where deptno = v_in_deptno;
if v_out_cursor is null then
raise nodata;
end if;
--異常處理
exception
when nodata then
dbms_output.put_line('沒有該部門!');
end;
--3.建立一個塊,用於測試儲存過程
declare
v_cursor pack_cursor.dept_corsor;
v_deptno emp.deptno%type :=&input;
v_name emp.ename%type;
v_empno emp.empno%type;
v_sal emp.sal%type;
begin
pro_cursor(v_deptno,v_cursor);
--執行遊標
fetch v_cursor into v_empno,v_name,v_sal,v_deptno;
while v_cursor%found loop
dbms_output.put_line('員工編號:' || v_empno || ' 員工姓名:' || v_name || ' 薪資:' ||v_sal || ' 所屬部門:' || v_deptno );
fetch v_cursor into v_empno,v_name,v_sal,v_deptno;
end loop;
--關閉遊標
close v_cursor;
end;
--sql語句實現分頁:
select t2.* from (select t1.*,rownum as rn from (select * from emp) t1 where rownum <=10) t2 where rn >= 5;
--例項:建立一個儲存過程,實現分頁功能:
create or replace procedure paging(v_in_table in varchar2 , v_in_currPage in number,v_in_pageSize in number ,v_out_count out number
,v_out_pageCount out number, v_resultCursor out pack_cursor.dept_corsor ) is
v_start number; --開始的記錄
v_end number;--結束的記錄
v_sql_count varchar(50);
v_sql_page varchar2(2000);
v_count number ;-- 儲存總記錄數
v_pageSize number;--分頁顯示的記錄數
v_currPage number;--當前頁數
v_table varchar2(2000); --需要查詢的表明
begin
v_sql_count := 'select count(*) from ' || v_in_table;--獲得記錄數目
execute immediate v_sql_count into v_count ;
v_out_count := v_count;
v_currPage := v_in_currPage;
v_pageSize :=v_in_pageSize;
v_table := v_in_table;
--獲得頁面總數
if mod(v_count,v_in_pageSize) = 0 then
v_out_pageCount := v_count / v_pageSize;
else
v_out_pageCount := v_count / v_pageSize + 1;
end if;
--獲得當前頁面的記錄
v_start := v_pageSize *(v_currPage - 1) + 1;
v_end := v_pageSize * v_currPage;
v_sql_page := 'select t2.* from (select t1.*,rownum as rn from (select empno,ename,sal,deptno from ' || v_table || ') t1 where rownum <= ' || v_end || ') t2 where rn >= ' || v_start;
open v_resultCursor for v_sql_page;
end;
declare
v_table varchar2(20):= '&input';
v_out_count number;
begin
-- execute immediate 'select count(*) from ' || v_table into v_out_count ;
dbms_output.put_line(v_out_count);
end;