1 --創建一個函數,用來根據部門編號返回調薪幅度 2 create or replace function get_ratio_by_dept(deptno varchar2) 3 return number is 4 n_salaryratio number(10,2); --調薪比率返回值變量 5 begin 6 case deptno 7 when 10 then 8 n_salaryratio:=1.09; 9 when 20 then 10 n_salaryratio:=1.11; 11 when 30 then 12 n_salaryratio:=1.18; 13 else 14 n_salaryratio:=0; 15 end case; 16 return n_salaryratio; 17 end; 18 19 begin 20 dbms_output.put_line(get_ratio_by_dept(20)); 21 end; 22 23 --創建一個存儲過程,用來實現加薪,它將調用get_ratio_by_dept來獲取加薪幅度 24 25 create or replace procedure raise_salary(p_empno number) 26 as 27 v_deptno number(2); 28 v_ratio number(10,2); --存儲調薪幅度變量 29 begin 30 select deptno into v_deptno from emp where empno=p_empno; 31 v_ratio:=get_ratio_by_dept(v_deptno); 32 if v_ratio>0 33 then 34 update scott.emp 35 set sal =sal* (1+v_ratio) 36 where empno = p_empno; 37 end if; 38 dbms_output.put_line('加薪成功!'); 39 exception 40 when no_data_found then 41 dbms_output.put_line('沒有找到該員工的任何信息!'); 42 when others then 43 dbms_output.put_line('調整薪資時出現了錯誤!'); 44 end; 45 46 set serveroutput on; 47 exec raise_salary(7369); 48 49 --創建包頭 50 create or replace package emp_sal_pkg as 51 function get_ratio_by_dept(deptno varchar2) return number; 52 procedure raise_salary(p_empno number); 53 end emp_sal_pkg; 54 55 --創建包體 56 create or replace package body emp_sal_pkg as 57 function get_ratio_by_dept(deptno varchar2) 58 return number 59 is 60 n_salaryratio number(10,2); 61 begin 62 case deptno 63 when 10 then 64 n_salaryratio:=1.09; 65 when 20 then 66 n_salaryratio:=1.11; 67 when 30 then 68 n_salaryratio:=1.18; 69 else 70 n_salaryratio:=1; 71 end case; 72 return n_salaryratio; 73 end get_ratio_by_dept; 74 75 procedure raise_salary (p_empno number) 76 as 77 v_deptno number(2); 78 v_ratio number(10,2); 79 begin 80 select deptno into v_deptno from emp where empno=p_empno; 81 v_ratio:=get_ratio_by_dept(v_deptno); 82 if v_ratio>0 83 then 84 update scott.emp 85 set sal =sal* (1+v_ratio) 86 where empno = p_empno; 87 end if; 88 dbms_output.put_line('加薪成功!'); 89 exception 90 when no_data_found then 91 dbms_output.put_line('沒有找到該員工的任何信息!'); 92 when others then 93 dbms_output.put_line('調整薪資時出現了錯誤!'); 94 end raise_salary; 95 end emp_sal_pkg; 96 --創建過程添加新員工 97 create or replace procedure AddNewEmp(p_empno emp.empno%type, 98 p_ename emp.ename%type, 99 p_job emp.job%type, 100 p_sal emp.sal%type, 101 p_deptno emp.deptno%type:=20) 102 as 103 begin 104 if p_empno<0 then 105 raise_application_error(-20001,'員工編號必須大於0'); 106 end if; 107 insert into emp 108 (empno,ename,job,sal,deptno) 109 values (p_empno,p_ename,p_job,p_sal,p_deptno); 110 end AddNewEmp; 111 112 begin 113 AddNewEmp(8236,'諸葛亮','策划人員',25000,40); 114 end; 115 116 117 118 子程序創建高度可維護,重用的代碼 119 (1)模塊化代碼(2)簡化應用程序(3)提升管理性:需求變更,只要改子程序 120 (4)可重用性,提高性能 121 程序調試 122 C+R 直接運行 C+N單擊進入 C+O單步逃過 C+T單步退出 123 --在過程中使用return語句 124 create or replace procedure RaiseSalary( 125 p_empno emp.empno%type) as 126 v_job emp.job%type; 127 v_sal emp.sal%type; 128 begin 129 select job,sal into v_job,v_sal from emp 130 where empno=p_empno; 131 if v_job<>'CLERK' then 132 return; --如果不是職員則退出 133 elsif v_sal>3000 then 134 return ; 135 else 136 --否則更新薪資記錄 137 update emp set sal=Round(sal*1.12,2) where 138 empno=p_empno; 139 end if; 140 exception 141 when no_data_found then 142 dbms_output.put_line('沒有找到員工記錄'); 143 end RaiseSalary; 144 begin 145 RaiseSalary(7369); 146 end; 147 select * from emp where empno=7369; 148 --查詢當前scott方案下的過程和函數列表 149 select object_name,object_type,created, 150 last_ddl_time,status,temporary 151 from user_objects 152 where object_type in ('PROCEDURE','FUNCTION','TABLE'); 153 154 155 --in out 模式參數 156 create or replace procedure calcRaiseSalary( 157 p_job in varchar2, 158 p_salary in out number 159 ) as 160 v_sal number(10,2); 161 v_job varchar2(10); 162 begin 163 if p_job='CLERK' then 164 v_sal:=p_salary*1.12; 165 166 elsif p_job='銷售人員' then 167 v_sal:=p_salary*1.18; 168 elsif p_job='經理' then 169 v_sal:=p_salary*1.19; 170 else 171 v_sal:=p_salary; 172 173 end if; 174 p_salary:=v_sal; ---值傳遞 175 176 end calcRaiseSalary; 177 178 declare 179 v_sal number(10,2); 180 v_job varchar2(10); 181 begin 182 select sal,job into v_sal,v_job from emp where 183 empno=7369; 184 calcRaiseSalary(v_job,v_sal); 185 dbms_output.put_line('計算后的調整薪水為:'||v_sal); --||'JOB'||v_jo 186 end; 187 188 select * from emp where empno=7369; 189 190 引用傳遞:將實際參數的指針(內存地址)傳遞給形式參數, 191 值傳遞:將實際參數的值賦給形式參數,值拷貝,指向不同的內存地址 192 193 如果參數是大型數據結構,比如集合,記錄和對象實例, 參數復制會大大降低執行速度, 194 消耗內存 195 nocopy 使得out和in out模式的參數按引用進行傳遞 196 197 198 199 200 201 202 --編譯包規范 203 alter package emp_pkg_overloading compile specification; 204 --編譯包體 205 alter package emp_pkg_overloading compile body; 206 --同時編譯包規范和包體 207 alter package emp_pkg_overloading compile package; 208 209 --查詢包規范和包體信息 210 select object_name,object_type,created,last_ddl_time from user_objects 211 where object_type in ('PACKAGE','PACKAGE BODY'); 212 213 --查看包的源代碼 214 select line,text from user_source where name='EMP_MGMT_PKG_OVERLOADING' 215 and type='PACKAGE'; 216 217 218 --使用returning into 為記錄變量賦值 219 declare 220 type t_emp is record( 221 empno emp.empno%type, 222 ename emp.ename%type, 223 sal emp.sal%type 224 ); 225 emp_info t_emp; 226 old_sal emp.sal%type; 227 begin 228 select sal into old_sal 229 from emp 230 where empno=7369; 231 update emp 232 set sal=sal*1.1 233 where empno=7369 234 returning empno,ename,sal into emp_info; 235 dbms_output.put_line( 236 emp_info.empno||' '||emp_info.ename ||' '|| 237 old_sal||' '|| emp_info.sal); 238 239 end; 240 select sal,ename from emp where empno =7369 241 242 --在insert語句中使用記錄類型 243 declare 244 type t_dept_rec is record( 245 rec_deptno number, 246 rec_dname varchar2(14), 247 rec_loc varchar2(13) 248 ); 249 rec_dept_1 t_dept_rec; 250 rec_dept_2 dept%rowtype; 251 begin 252 rec_dept_1.rec_deptno:=71; 253 rec_dept_1.rec_dname:='系統部'; 254 rec_dept_1.rec_loc:='上海'; 255 insert into dept values rec_dept_1; 256 rec_dept_2.deptno:=72; 257 rec_dept_2.dname:='開發部'; 258 rec_dept_2.loc:='重慶'; 259 insert into dept values rec_dept_2; 260 end; 261 262 select * from dept 263 264 265 --在update語句中使用記錄類型 266 declare 267 rec_dept_2 dept%rowtype; 268 begin 269 rec_dept_2.deptno:=20; 270 rec_dept_2.dname:='系統部'; 271 rec_dept_2.loc:='上海'; 272 update dept set row=rec_dept_2 where deptno=rec_dept_2.deptno; 273 end; 274 275 使用記錄類型的限制 276 (1)記錄類型不能出現在select語句的選擇列表, where子句,group by 子句 277 或order by子句中 278 (2)update語句中Row關鍵字只能出現在set語句之后,並且不能和子查詢連用 279 (3)不能包含其他的變量和值,不能具有嵌套的記錄類型,不支持在 280 execute immediate 語句中使用記錄類型.