oracle學習儲存過程
1, create or replace procedure sp_pro is
begin
insert into mytest values('123','wangwu');
end;;
檢視錯誤: show error;
執行: /
2,呼叫;
exec 過程名(引數,引數);
call 過程名(引數,引數,....);
3,塊(程式設計)-->過程,函式,包,觸發器
命名規範: 變數v_字首v_sal , 常量c_字首c_rate; 遊標_cursor字尾emp_cursor; 異常e_字首e_error;
declear 定義常量、變數、遊標、例外異常、複雜資料型別,
begin執行sql語句, exception 異常處理, end;
set serveroutput on --開啟輸出選項;
declare --定義變數
v_ename varchar2(5);
v_sal number(7,2);
begin
select ename,sal into v_ename, v_sal from emp where empno=&no; --將查詢出來的ename放入到引數v_ename中,&表示從控制檯接受輸入的變數; 引數順序要一致
dbms_output.put_line('僱員名:'||v_ename); --控制檯輸出
dbms_output.put_line('hello');
exception --異常處理
when no_data_found then
dbms_output.put_line('資料輸入錯誤');
end;
4,異常例外: no_data_found 資料不存在
create procedure sp_pro3(spName varchar2, newSal number) is ---引數只指定型別不指定大小
begin
update emp set sal=newSal where ename=spName; --根據使用者名稱修改工資
end;
exec sp_pro3('scott', 4678); --呼叫過程
java呼叫:
CallableStatement cs=conn.prepareCall("{call sp_pro3(?,?)}");
cs.setString(1,"Tom");//給? 賦值
cs.setInt(2,1000);
cs.execute(); //執行
java呼叫有返回值的儲存過程:
CallableStatement cs=conn.prepareCall("{call sp_pro8(?,?)}");//第一個引數是入引數,第二個是出引數
cs.setString(1,"Tom");//給第一個? 賦值
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.oracleTypes.VARCHAR); //過程的第二個引數為輸出引數,型別要一致
cs.execute(); //執行
//取出返回值,要注意?順序
String name=cs.getString(2); //得到過程的返回值
5 建立函式:
crete function sp_fun2(spName varchar2) --引數不定義大小
return number is yearSal number(7,2);
begin
select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=spName;
return yearSal;
end;
函式呼叫:
var abc number;
call sp_fun2('scott') into :abc;
print abc
java程式中呼叫函式:
select sp_fun('scott') from dual;//通過rs.get(1)得到返回的結果。
6 包: 用於邏輯上組合過程和函式,它有包規範和包體兩部分組成;
create package sp_package is
procedure update_sal(name varchar2, newsal number);
function annual_income(name varchar2) return number;
end;
包規範只包含了過程和函式的說明,但是沒有過程和函式的實現程式碼。包體用於實現包規範中的過程和函式。
建立包體: create package body sp_package is
procedure update_sal(name varchar2, newsal number)
is
begin
update emp set sal=newsal where ename=name;
end;
function annual_income(name varchar2)
return unmber is
annual_salary number;
begin
select sal*12+nvl(comm,0) into annual_salary from emp where ename=name;
return annual_salary;
end;
end;
呼叫執行: call sp_package.update_sal('tom',120);
7 定義變數:
1),定義一個變長字串 v_ename varchar2(10);
2), 定義一個小數範圍 -9999.99 ~ 9999.99
v_sal number(6.2);
3),定義一個小數並初始值為5.4 ,:=是賦值號
v_sal2 number:=5.4;
4) 定義一個日期型別的資料
v_brithdate date;
5) 定義一個布林變數,不能為空,初始值為false
v_valid boolean not null default false;
8,複合變數:記錄型別,表型別
declare
type emp_record is record( name emp.ename%type, sal emp.sal%type); --定義一個記錄型別
sp_record emp_record; --定義一個記錄變數
begin
select ename,sal into sp_record from emp where empno=7788; --賦值
dbms_output.put_line('員工名: '|| sp_record.name); --獲取
end;
------------表型別相當於陣列------------------------
declare
type sp_table_type is table of emp.ename%type index by binary_integer; --下標為整數可以為負數
sp_table sp_table_type; --定義一個表型別的變數
begin
select ename intosp_table(0) from emp where empno=7788; --賦值,下標為0,只能接受一行的記錄
dbms_output.put_line('員工名: '||sp_table(0)); --獲取
end;
9,參照表裡:遊標cursor
declare
type sp_emp_cursor is ref cursor; --定義一個遊標型別
sp_cursor sp_emp_cursor; --定義一個遊標變數
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open sp_currsor for select ename,sal from emp where deptno=10; --遊標與一個select結合
loop
fetch sp_currsor into v_ename,v_sal;--從遊標獲取資料賦值給變數
exit when sp_curror%notfound; --判斷是否為空
dbms_output.put_line('名字: '||v_ename||'工資: '||v_sal);
end loop;
end;
帶引數的遊標:
declare
cursor c_emp(p_deptno employees.department_id%type)is
select * from hr.employees where department_id=p_deptno;
v_emp c_emp%ROWTYPE;
begin
open c_emp(10);
loop
fetch c_emp into v_emp;
exit when c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.employ_id||v_emp.last_name);
end loop;
close .c_emp;
10, 返回結果集的儲存過程
--1,建立一個包,在該包中,定義型別test_sursor, 是個遊標
create or replace package testpackage as
type test_cursor is ref cursor;
end tespackage;
--2 建立過程
create or replace procedure sp_pro9(spNo in number, p_cursor out tespackage.test_cursor)
is
begin
open p_cursor for select * from emp where deptno =spno;
end;
java呼叫返回的是結果集:
CallableStatement cs=conn.prepareCall("{call sp_pro9(?,?)}");//第一個引數是入引數,第二個是遊標出引數
cs.setString(1,10);//給第一個? 賦值
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.oracleTypes.CURSOR); //過程的第二個引數為遊標輸出引數,型別要一致
cs.execute(); //執行
ResultSet rs=(ResultSet)cs.getobject(2); //得到結果集
while(rs.next()){
syso(rs.getInt(1)+' '+rs.getString(2) ); //迭代取出資料,第一列和第二列
}
10,if控制
if v_job='pro' then
update emp set sal=sal+1000 where empno=spNo;
elsif v_job='MAN' then
update emp set sal=sal+500 where empno=spNo;
else
update emp set sal=sal+200 where empno=spNo;
end if;
觸發器:create trigger
11.迴圈:
方式一:
loop
insert into users values(v_num, spname);
exit when v_num=10;--判斷是否退出迴圈,符合條件退出
end loop;
方式二:
while v_num<=20 loop --符合條件才執行
insert into users values(v_num, spname);
v_num:=v_num+1;
end loop;
方式三:
for i in 1..10 loop
insert into users values(v_num, spname);
end loop;
12, goto語句
declare
i int :=-1;
begin
loop
dbms_output.put_line('輸出i='||i);
if i=10 then
goto end_loop; --跳轉到特定標號處
end if;
i:=i+1;
end loop;
<<end_loop>>
dbms_output.put_line('迴圈結束');
end;
13, null語句不會執行任何操作,
14,分頁演算法
--1,建立一個包,在該包中,定義型別test_sursor, 是個遊標
create or replace package testpackage as
type test_cursor is ref cursor;
end tespackage;
--2 建立過程
create or replace procedure fenye (
tableName in varchar2, --表名
pagesize in number, --每頁顯示記錄數
pageNow in number, --顯示第幾頁
myrows out number, --總記錄數
mypagecount out number,總頁數
p_cursor out testpackage.test_cursor --返回的結果集
) is
---定義變數
v_sql varchar2(1000);
v_begin number:=(pageNow-1)*pagesize+1; --計算顯示頁的第一條記錄
v_end number:=pageNow*pagesize; --計算顯示頁的第二條記錄
begin
v_sql:='select * from (select t.* , rownum rn from(select * from '|| tableName||') t where rownum<='|| v_end||' ) where rn >='||v_begin;
open p_cursor for v_sql;
v_sql:='select count(*) from '||tablesName;
execute immediate v_sql into myrows; --表的總記錄數
if mod(myrows, pagesize)=0 then --計算總頁數
mypageCount := myrows/Pagesize;
else
myPageCount :=myrows/Pagesize+1;
end if;
close p_cursor; --關閉遊標
end;
15,case語句
create or replace procedure sp_pro6(spno number) is
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno=spno;
case
when v_sal <1000 then
update emp set sal=sal+100 where empno=spno;
when v_sal <2000 then
update emp set sal=sal+200 where empno=spno;
end case;
exception
when case_not_found then
dbms_output.put_line('case沒有相匹配的');
end;
16例外:
case_not_found case中沒有相對應的條件
cursor_already_open 遊標已經開啟
dup_val_on_index 唯一索引重複插入inser語句
invaild_cursor 從未開啟的遊標中提取資料,關閉沒有開啟的遊標
invalid_number 輸入的資料有誤比如100輸成LOO
no_data_found 當select中沒有返回行
too_many_rows 當select返回超過了一行,返回了多行
zero_divide 當執行3/0會觸發該例外,分母不能為0
value_error 賦值操作變數的長度不足以容納實際資料
自定義例外
create or replace procedure ex_test(spNo number)
is
myex exception; --定義一個自定義例外
begin
update emp set sal=sal+1000 where empno=spNo;
if sql%notfound then --這是表示沒有更新成功
raise myex; --觸發myex
end if;
exception
when myex then
dbms_output.put_line('沒有更新任何使用者');
end;
呼叫:exec ex_test(56);
17,檢視view
create or replace view 檢視名 as select 語句 [ with read only]只可讀不可改
刪除檢視 : drop view 檢視名
eg: create view myview as select * from emp where sal<1000;
18,當語句中包含單引號使用q加分割符號
v_event := q'!Father's day!'; 前面加q其中!為分割符號
v_event :=q'[Mother's day]'; 前面加q其中[]為分割符號
v_event :='Father''s day'; 雙單引號
19:儲存過程迴圈
儲存過程for迴圈:
create or replace package body update_payend_status is
procedure updatestatus(mkey varchar2,accountid number)is
v_sumUnits float :=0;
v_flag pglumpsum.flag%type;
v_mkey pglumpsum.mkey%type;
begin
open getPenFlag(mkey);
fetch getPenFlag into v_flag;
close getPenFlag;
open getAllPayendMembers;
loop
fetch getAllPayendMembers into v_mkey,v_accountid;
exit when getAllPayendMembers%NOTFOUND;
addCalc(v_mkey,v_accoutid);
end loop;
close getAllPayendMembers;
end;
END;
20, -----先建立序列,再建立觸發器
create sequence SEQ_FIXED_TRADEDATE
minvalue 1
maxvalue 9999999
start with 3
increment by 1
nocache;
--建立觸發器
create or replace trigger tg_fixed_Tradedate
before insert on fixed_Tradedate for each row --定義before觸發器,監測表fixed_tradedate的插入操作,行級別的觸發器
when (new.ID is null)
begin
select SEQ_FIXED_TRADEDATE.nextval into:new.ID from dual;
end;
---刪除序列
drop sequence SEQ_FIXED_TRADEDATE;
--建立同義詞
create sysnonym client_54,user for fe.user;
--刪除同義詞
drop sysnonym user;
--授權
grant select ,insert,update,execute on payment_batch_proc to client_54;
--增加對錶空間的許可權
alter user client_54 quota unlimited on users;