Oracle資料庫的遊標和for迴圈使用 Oracle資料庫的遊標和for迴圈使用
Oracle資料庫的遊標和for迴圈使用
1. 遊標的概念和作用
- 遊標是 sql 的一個記憶體工作區,由系統或使用者以變數的形式定義
- 遊標的作用就是用於臨時儲存從資料庫中提取的資料塊(結果集)。
- 它有一個
指標
,從上往下移動(fetch
),從而能夠遍歷每條記錄。 - 用
犧牲記憶體
來提升 SQL 執行效率,適用於 大資料處理。
(摘抄自https://blog.csdn.net/qq_34745941/java/article/details/81294166)。
2.遊標結構圖
3.具體用法
遊標有四大屬性,分別是
1. “SQL%ISOPEN” :布林型別。判斷遊標是否開啟
2.“SQL%FOUND”:布林型別。判斷上一條fetch語句是否有值,有則為true,否則為false;
3.“SQL%NOTFOUND”:布林型別。與2相反,常用作退出迴圈的條件。
4.“SQL%ROWCOUNT”:整型。當前成功執行更改的資料行數。
3.1 靜態遊標
3.1.1 隱式遊標
使用DML操作(增刪改)或select……into……會自動建立隱式遊標,名稱是“sql”,該遊標會自動宣告,開啟和關閉。無需人為開啟或關閉。
create or replace procedure ATest( O_Result Out VarChar2 )is v_id staff.id%type; begin insert into staff(id,name) values(1,'張三'); if sql%found then O_Result:='新增成功'; end if; update staff set name = '李四'where id = 1; if sql%found then O_Result:='更新成功'; end if; delete from staff where id = 1; if sql%found then O_Result:='刪除成功'; end if; select id into v_id from staff; if sql%found then O_Result:='查詢成功'; end if; if sql%isopen then O_Result:='遊標為開啟狀態,但不可能走到這一步'; --遊標只有在執行上述增刪改操作才會開啟並自動關閉 else O_Result:='遊標為關閉狀態'; end if; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
3.1.2 顯式遊標
顯示遊標又分為不帶引數和帶引數兩種
無參:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; cursor v_cur is --宣告遊標 為staff表的資料集 select * from staff; begin open v_cur; --開啟遊標 fetch v_cur into v_cur_info; --賦值給遊標 O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name;--輸出值 close v_cur; --關閉遊標 exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
輸出結果: ID:1,Name:張三
帶參:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; cursor v_cur(v_id staff.id%type) is --宣告遊標 為staff表的資料集 select * from staff where id =v_id; --引數:v_id begin open v_cur(1); --開啟遊標 fetch v_cur into v_cur_info; --賦值給遊標 O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name; close v_cur; --關閉遊標 exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
輸出結果: ID:1,Name:張三
3.2 動態遊標
3.2.1 自定義型別遊標
自定義遊標型別宣告寫法:
TYPE ref_type_name IS REF CURSOR [RETURN return_type];
ref_type_name代表我們自定義型別的名稱,cursor是系統預設的
return_type代表資料庫表中的一行,或一個記錄型別,是一個返回型別;
返回值不是必要的,無返回值則稱為弱型別,更加靈活;有返回值稱為強型別,減少錯誤;
弱型別寫法:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; type v_cur_type is ref cursor; --自定義遊標型別 v_cur v_cur_type; begin open v_cur for --開啟遊標並宣告 select * from staff where id<5; loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
另一種寫法:
create or replace procedure ATest( O_Result Out VarChar2 )is v_sql varchar(1000); v_param staff.id%type:=5; v_cur_info staff%rowtype; type v_cur_type is ref cursor; --自定義遊標型別 v_cur v_cur_type; begin v_sql:='select * from staff where id <:id'; open v_cur for v_sql --開啟遊標並宣告 using v_param; --繫結引數方法 loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
強型別寫法:
三個注意事項:
1.強型別無法使用繫結引數方法
2.for後面必須是sql,不能是字串,如上面的v_sql;
3.引數必須對應;
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; type v_cur_type is ref cursor return staff%rowtype ; --自定義遊標型別 v_cur v_cur_type; begin open v_cur for --開啟遊標並宣告 select * from staff where id <5; loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
3.2.2 系統型別遊標
簡寫手動宣告自定義遊標的過程
type v_cur_type is ref cursor return staff%rowtype ; --自定義遊標型別 v_cur v_cur_type;
等同於 v_cur sys_refcursor;
4.效率問題
沒有實際測試過,根據其他部落格總結是這樣:一般來說批量處理的速度要最好,隱式遊標的次之,單條處理的最差
以下是示例:
1、批量處理 open 遊標; loop fetch 遊標 bulk collect into 集合變數(也就是 table 型別哦) limit 數值; -- 一般 500 左右 exit when 條件 --(變數.count = 0,如果用 sql%notfound 不足 limit 的記錄就不會被執行哦) close 遊標; 2、隱式遊標 for x in (sql 語句) loop ... 邏輯處理 end loop; 3、單條處理 open 遊標; loop fetch 遊標 into 變數; exit when 條件 end loop; close 遊標; ———————————————— 原文連結:https://blog.csdn.net/qq_34745941/java/article/details/81294166
批量處理的關鍵字不是很瞭解,下次學習下在記錄起來;
隱式遊標寫法最簡潔明瞭,類似於程式中的for迴圈寫法;
單條處理大概就是上面那些範例的寫法。
1. 遊標的概念和作用
- 遊標是 sql 的一個記憶體工作區,由系統或使用者以變數的形式定義
- 遊標的作用就是用於臨時儲存從資料庫中提取的資料塊(結果集)。
- 它有一個
指標
,從上往下移動(fetch
),從而能夠遍歷每條記錄。 - 用
犧牲記憶體
來提升 SQL 執行效率,適用於 大資料處理。
(摘抄自https://blog.csdn.net/qq_34745941/java/article/details/81294166)。
2.遊標結構圖
3.具體用法
遊標有四大屬性,分別是
1. “SQL%ISOPEN” :布林型別。判斷遊標是否開啟
2.“SQL%FOUND”:布林型別。判斷上一條fetch語句是否有值,有則為true,否則為false;
3.“SQL%NOTFOUND”:布林型別。與2相反,常用作退出迴圈的條件。
4.“SQL%ROWCOUNT”:整型。當前成功執行更改的資料行數。
3.1 靜態遊標
3.1.1 隱式遊標
使用DML操作(增刪改)或select……into……會自動建立隱式遊標,名稱是“sql”,該遊標會自動宣告,開啟和關閉。無需人為開啟或關閉。
create or replace procedure ATest( O_Result Out VarChar2 )is v_id staff.id%type; begin insert into staff(id,name) values(1,'張三'); if sql%found then O_Result:='新增成功'; end if; update staff set name = '李四'where id = 1; if sql%found then O_Result:='更新成功'; end if; delete from staff where id = 1; if sql%found then O_Result:='刪除成功'; end if; select id into v_id from staff; if sql%found then O_Result:='查詢成功'; end if; if sql%isopen then O_Result:='遊標為開啟狀態,但不可能走到這一步'; --遊標只有在執行上述增刪改操作才會開啟並自動關閉 else O_Result:='遊標為關閉狀態'; end if; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
3.1.2 顯式遊標
顯示遊標又分為不帶引數和帶引數兩種
無參:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; cursor v_cur is --宣告遊標 為staff表的資料集 select * from staff; begin open v_cur; --開啟遊標 fetch v_cur into v_cur_info; --賦值給遊標 O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name;--輸出值 close v_cur; --關閉遊標 exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
輸出結果: ID:1,Name:張三
帶參:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; cursor v_cur(v_id staff.id%type) is --宣告遊標 為staff表的資料集 select * from staff where id =v_id; --引數:v_id begin open v_cur(1); --開啟遊標 fetch v_cur into v_cur_info; --賦值給遊標 O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name; close v_cur; --關閉遊標 exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
輸出結果: ID:1,Name:張三
3.2 動態遊標
3.2.1 自定義型別遊標
自定義遊標型別宣告寫法:
TYPE ref_type_name IS REF CURSOR [RETURN return_type];
ref_type_name代表我們自定義型別的名稱,cursor是系統預設的
return_type代表資料庫表中的一行,或一個記錄型別,是一個返回型別;
返回值不是必要的,無返回值則稱為弱型別,更加靈活;有返回值稱為強型別,減少錯誤;
弱型別寫法:
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; type v_cur_type is ref cursor; --自定義遊標型別 v_cur v_cur_type; begin open v_cur for --開啟遊標並宣告 select * from staff where id<5; loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
另一種寫法:
create or replace procedure ATest( O_Result Out VarChar2 )is v_sql varchar(1000); v_param staff.id%type:=5; v_cur_info staff%rowtype; type v_cur_type is ref cursor; --自定義遊標型別 v_cur v_cur_type; begin v_sql:='select * from staff where id <:id'; open v_cur for v_sql --開啟遊標並宣告 using v_param; --繫結引數方法 loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
強型別寫法:
三個注意事項:
1.強型別無法使用繫結引數方法
2.for後面必須是sql,不能是字串,如上面的v_sql;
3.引數必須對應;
create or replace procedure ATest( O_Result Out VarChar2 )is v_cur_info staff%rowtype; type v_cur_type is ref cursor return staff%rowtype ; --自定義遊標型別 v_cur v_cur_type; begin open v_cur for --開啟遊標並宣告 select * from staff where id <5; loop --開始迴圈 fetch v_cur into v_cur_info; -- 賦值 exit when v_cur%notfound; --判斷沒有值就退出迴圈 O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name; end loop; close v_cur; exception when Others then begin O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM; rollback; end; end;
3.2.2 系統型別遊標
簡寫手動宣告自定義遊標的過程
type v_cur_type is ref cursor return staff%rowtype ; --自定義遊標型別 v_cur v_cur_type;
等同於 v_cur sys_refcursor;
4.效率問題
沒有實際測試過,根據其他部落格總結是這樣:一般來說批量處理的速度要最好,隱式遊標的次之,單條處理的最差
以下是示例:
1、批量處理 open 遊標; loop fetch 遊標 bulk collect into 集合變數(也就是 table 型別哦) limit 數值; -- 一般 500 左右 exit when 條件 --(變數.count = 0,如果用 sql%notfound 不足 limit 的記錄就不會被執行哦) close 遊標; 2、隱式遊標 for x in (sql 語句) loop ... 邏輯處理 end loop; 3、單條處理 open 遊標; loop fetch 遊標 into 變數; exit when 條件 end loop; close 遊標; ———————————————— 原文連結:https://blog.csdn.net/qq_34745941/java/article/details/81294166
批量處理的關鍵字不是很瞭解,下次學習下在記錄起來;
隱式遊標寫法最簡潔明瞭,類似於程式中的for迴圈寫法;
單條處理大概就是上面那些範例的寫法。