ORACLE PLSQL程式碼塊學習
背景:
本人小小實習生,oracle小白,,剛剛接觸oracle的plsql塊。記錄下來這個學習過程,有錯麻煩各位指出。
情景:
通過遍歷查詢一個表的結果集,得到結果集中每行結果中的其中一個欄位的值,作為另一個查詢的where語句查詢條件。
之前的解決方案是在service層中遍歷第一次查詢的結果集,然後在這個遍歷過程中多次呼叫第二個查詢的方法,這就導致了在控制層和業務邏輯層只需要一個方法,但到了資料交換層需要分開為兩個方法,很繁瑣。恰巧之前有了解到oracle中可以通過儲存函式實現這個功能,所以學習了下plsql塊。
預備知識:
1.plsql程式碼塊基本語法:
DECLARE
--這裡宣告一些變數②和遊標 ③
BEGIN
--需要執行的邏輯 包括一些遊標遍歷
EXCEPTION
--發生異常的邏輯
END;
2.Oracle中變數型別
這裡我就列舉下我目前使用到
NUMBER(p,s) 數值型別 p表示精度 s表示小數長度
例如 NUMBER(3,2) 表示的是 整數部分最大是1位,小數部分是2位的數
NUMBER等同於NUMBER(5)
INT
VARCHAR
CHAR
表%ROWTYPE 例如 emp表中有 id,name,dept 三個欄位, emp_row emp%ROWTYPE ,變數emp_row 同樣有 id,name,dept三個欄位。
表.欄位%TYPE 例如 emp.id 是number型別的, emp_id emp.id%type 則表示變數emp_id和emp表的id欄位是相同的。
3.Oracle遊標
參考 http://www.iteye.com/topic/649874
遊標的概念:遊標是SQL的一個記憶體工作區,由系統或使用者以變數的形式定義。
遊標的作用:用於臨時儲存從資料庫中提取的資料塊。
我將遊標理解為java中jdbc中的resultset 物件,相當於一個記錄查詢結果的虛擬表,如果想拿到其中的資料需要遍歷。
遊標的應用:
屬性:
SQL%FOUND FETCH有結果則為true
SQL%NOTFOUND FETCH無結果為true
SQL%ISOPEN 遊標開啟為true
SQL%ROWCOUNT 返回當前記錄在遊標中的行數
隱式遊標
預設起名字SQL,不用我們開啟也不用關閉.DML語句會自動生成隱式遊標,主要起到程式控制的作用。
顯示遊標
宣告方式: CURSOR mycursor IS select * from emp where id >5; 查詢結果將會記錄到遊標 mycursor中
REF遊標(動態遊標)
//TODO
遊標的遍歷方式
FOR i IN mycursor LOOP --這種方式會自動開啟遊標和關閉遊標,因此務必不要重複開啟,我出現過錯誤。
DBMS_OUTPUT.PUTLINE(i.id||i.name||i.dept); --i就有點類似於foreach 中的那個變數
END LOOP;
OPEN mycursor;
LOOP
FETCH mycursor INTO rs; --FETCH類似java中iterator遍歷集合的next() 即拿到了下一個元素同時將迭代指標指向下下個元素
EXIT WHEN mycursor%NOTFOUND;
END LOOP;
解決的問題:
根據產品id去查詢改產品有幾種顏色型別,遍歷這些顏色型別,每一個顏色型別找到一張圖片及一些其它相關的資料。總共需要查詢三個表
code:
declare
v_pid product.id%type default 877594; --為了以後學習儲存函式做準備,這裡設定預設值
cursor colorlist is
select color_type from productpic where productid=v_pid group by color_type;
v_colorid productpic.color_type%type;
cl_id int;
cursor v_result is
select * from(
select p.cmsimage imageurl,
p.productid pid,
p.type imagetypeid,
p.color_type colorid,
c.color_name colorname,
c.code colorcode,
pt.name imagetypename,
p.priority pr,
pt.priority priority,
p.id imageid
from productpic p,catalog_imagecolor c,productpic_type pt
where p.productid = v_pid
and p.color_type = cl_id
and p.type in(0,11)
and p.color_type = c.id
and p.type = pt.id
order by p.priority
)where rownum=1;
begin
for cl in colorlist loop --遍歷第一個遊標 在遊標遍歷過程中遍歷第二個遊標
if cl.color_type<>0 then
-- dbms_output.put_line('current colorid: '||cl.color_type);
cl_id :=cl.color_type;
if v_result%isopen then
close v_result;
end if;
for rs in v_result --遍歷第二個遊標
loop
dbms_output.put_line('current imageurl: '||rs.imageurl);
end loop ;
end if;
end loop;
exception
when others then
dbms_output.put_line('error!');
end;
總結:
通過plsql可以看出,原先需要在業務邏輯層做的判斷和資料交換層分成兩個方法的麻煩事,實際上在oracle中只需要寫到一個儲存函式中就可以解決,同時也方便之後的維護和呼叫。
第一次寫部落格,希望自己能堅持下去。