自己總結的包和過程的筆記
需要建立兩部分
建立包的說明
createor replace package EMPLOYEE_PKG
as
procedure PRINT_ENAME;
end EMPLOYEE_PKG;
建立包體
CREATEOR REPLACE PACKAGE BODY employee_pkg as
Procedure print_ename is
Begin
Dbms_output.put_line('ss');
End print_ename;
End employee_pkg;
包的其他例子
CREATEOR REPLACE PACKAGE globalPkg AUTHID CURRENT_USER AS
/* The following are T/SQL specific global variables. */
identity INTEGER;
trancount INTEGER := 0;
TYPE RCT1 IS REF CURSOR;/*new weakcursor definition*/
PROCEDURE incTrancount;
PROCEDURE decTrancount;
END globalPkg;
CREATE OR REPLACE PACKAGE BODY globalPkg AS
/* This is a dummy package body added by the migration
workbench in order to emulate T/SQLspecific global variables. */
PROCEDURE incTrancount IS
BEGIN
trancount := trancount + 1;
END incTrancount;
PROCEDURE decTrancount IS
BEGIN
trancount := trancount - 1;
END decTrancount;
END globalPkg;
(一) 過程的定義:
這些命名的PL/SQL塊成為存儲過程和函數,他們的集合、稱為程序包。
存儲過程
· 存儲於數據庫中的函數,過程是數據庫對象。叫存儲過程
· 存儲過程經編譯和優化後存儲在數據庫服務器中,使用時只要調用即可
我們可以命名我們的PL/SQL塊,並為他們確定參數,存儲在數據庫中。這樣可以從任何數據庫客戶端或者工具引用和運行他們,比如SQL*PLUS, Pro*C, JDBC。
(二) 優點:
1. 可重用性:一旦命名並保存在數據庫中後,任何應用都可以
2. 抽象和數據隱藏..
3. 可保證數據的安全性和完整性。
4. 存儲過程的能力大大增強了SQL語言的功能和靈活
性。存儲過程可以用流控語句編寫,有很強的靈
活性,可以完成復雜的判斷和較復雜的運算。
(三) 語法:
CREATE OR REPLACE
PROCEDURE name [ (parameter [,parameter,…] ) ] IS //或AS
[說明:變量定義於此]
BEGIN
執行語句序列
[EXCEPTION
例外處理程序
END [name ];
用戶通過create or repalce語句可以建立存儲於服務器端的存儲過程。存儲過程不能用於sql語句。(Procedures cannot be used in SQLstatements; )
Procedure有0或多個參數,參數可是(IN), output (OUT), (IN OUT)
類型.
執行存儲過程
set serveroutputon
/
直接執行:
execute my_proc
exec my_proc
(四) 權限:
表和視圖具有SELECT, INSERT, UPDATE, DELETE 這樣的特權,而過程具有EXECUTE特權。只有將EXECUTE特權賦予用戶,用戶才可以運行它。而將它賦予PUBLIC用戶,則所有用戶都可以運行。
其實我們可以將比較復雜的查詢寫成函數.然後到存儲過程中去調用這些函數.
(五) :Oracle中的函數與存儲過程的區別:
A:函數必須有返回值,而過程沒有.
B:函數可以單獨執行.而過程必須通過execute執行.
C:函數可以嵌入到SQL語句中執行.而過程不行.
(六) 過程裏要返回一個結果集,.就必須要用到遊標了!用遊標來處理這個結果集.
create or replaceprocedure Test
(
varEmpNameemp.ename%type
)
is begin ------會報錯.錯誤原因沒有into子句.
select * from empwhere ename like '%'||varEmpName||'%';
end;
這個程序我們無法用into,因為在Oracle裏面沒有一個類型去接受一個結果集.這個時候我們可以聲明遊標對象去接受他.
L/SQL遊標:
A:分類:
1:隱式遊標:非用戶明確聲明而產生的遊標. 你根本看不到cursor這個關鍵字.
2:顯示遊標:用戶明確通過cursor關鍵字來聲明的遊標.
B:什麽是隱式遊標:
1:什麽時候產生:
會在執行任何合法的SQL語句(DML---INSERTUPDATE DELETE DQL-----SELECT)中產生.他不一定存放數據.也有可能存放記錄集所影響的行數.
如果執行SELECT語句,這個時候遊標會存放數據.如果執行INSERT UPDATE DELETE會存放記錄影響的行數.
C:隱式遊標叫什麽名字:
名字叫sql
關於sql的遊標變量到底有哪些呢?
作用:返回最近一次執行SQL語句所涉及的遊標相關信息.因為每執行一次SQL語句,都會產生一個隱式遊標.那麽當前執行的SQL語句就是當前的隱式遊標.
sql%found
sql%notfound
sql%rowcount
sql%isopen
D:關於隱式遊標的例子:
create table 學生基本信息表
(
StuID int,
StuName varchar2(20)
)
alter table 學生基本信息表 addconstraint PK_STUID primary key(StuID)
declare
num int:=0;
begin
num:=#
delete from 學生基本信息表where StuID=num;
if sql%notfound then
dbms_output.put_line('該行數據沒有發現');
else
dbms_output.put_line('數據被發現並刪除,影響的行數為:'||sql%rowcount);
end if;
end;
E:關於顯示遊標的例子:
1:如何定義顯示遊標
declare cursor <cursor_name> is[select語句];
declare cursor mycur is selectempno,ename,job from scott.emp;
2:如何打開遊標:
open <cursor_name>;
open mycur;
3:如何通過遊標來讀取數據
fetch <cursor_name> into<variable_list>
4:如何關閉遊標:
close <cursor_name>;
close mycur;
註意:在Oracle中,不需要顯示銷毀遊標.因為在Oracle中,很多東西是由JAVA寫的.Oracle會自動銷毀遊標.
5:舉例:
declare
cursor mycur is select empno,ename,job fromemp;
vempno emp.empno%type;
vename emp.ename%type;
vjob emp.job%type;
begin
open mycur;
fetch mycur into vempno,vename,vjob;
dbms_output.put_line('I FoundYou!'||mycur%rowcount||'行');
dbms_output.put_line('讀取的數據為'||vempno||' '||vename||' '||vjob);
close mycur;
end;
因為只讀出來一條,所以要遍歷一下:
declare
cursor mycur is select empno,ename,job fromemp;
vempno emp.empno%type;
vename emp.ename%type;
vjob emp.job%type;
begin
open mycur;
loop
fetch mycur into vempno,vename,vjob;
exit when mycur%notfound;
if mycur%found then
dbms_output.put_line('讀取的數據為'||vempno||' '||vename||' '||vjob);
end if;
end loop;
dbms_output.put_line('I FoundYou!'||mycur%rowcount||'行');
close mycur;
end;
6:通常情況下我們在讀取表數據的時候,我們需要動態的去查詢.所以能不能在Oracle中給遊標帶參數呢?可以!
1):如何定義帶參數的遊標:
declare cursor <cursor_name>(參數名稱 參數類型描述) is select xxxxx from bbbbb where aaa==???and ccc=???;
2):例子:
遊標是一個集合,讀取數據有兩種方式
第一種方式: open fetch close
第二種方式: for 一但使用了for循環在循環剛剛開始的時候,相當於執行open,在處理循環的時候,相當於執行fetch,
在退出循環的時候,相當於執行了close
declare
cursor query(vnamevarchar) is select empno,ename,job from emp where ename like'%'||vname||'%';
begin
for line inquery('A')
loop
dbms_output.put_line(line.empno||''||line.ename||' '||line.job);
end loop;
end;
實現動態輸入:
declare
cursor query(vnamevarchar) is select empno,ename,job from emp where ename like'%'||vname||'%';
name1 varchar(10);
begin
name1:=upper('&name1');
for line in query(name1)
loop
dbms_output.put_line(line.empno||''||line.ename||' '||line.job);
end loop;
end;
使用REF遊標:
是一種引用類型,類似於指針。
顯式和隱式遊標的區別:
盡量使用隱式遊標,避免編寫附加的遊標控制代碼(聲明,打開,獲取,關閉),也不需要聲明變量來保存從遊標中獲取的數據。
REF CURSOR遊標:
動態遊標,在運行的時候才能確定遊標使用的查詢。分類:
強類型(限制)REF CURSOR,規定返回類型
弱類型(非限制)REFCURSOR,不規定返回類型,可以獲取任何結果集。
TYPE ref_cursor_name IS REF CURSOR[RETURN return_type]
使用REF CURSOR遊標:返回結果集合
create or replaceprocedure pro_shuijs(gh in varchar2, RC1 INOUT globalPkg.RCT1) is
begin
OPEN RC1 FOR
select a.zgbhao00 ,a.xming000,GZHJI000+je000000,nvl(SYBXIAN0,0)+nvl(YBAO0000,0)+nvl(YLBXIAN0,0)+nvl(GJJIN000,0) ,
je000000 補充保險,a.sdshui00 稅金
from rlvgzsjx2 a ,rltrsdawhxxb,rltdygzlsb c, rlvwcylgj1 d
where a.zgbhao00=c.zgbhao00(+) and
a.zgbhao00=d.zgbhao00(+) and a.nyue0000=d.nyue0000(+) and
a.zgbhao00=b.zgbhao00(+) and a.zgbhao00=gh ;
end pro_shuijs;
自己總結的包和過程的筆記