資料庫遊標學習記錄
一、遊標的定義:遊標是一個容器,用來記錄查詢結果集的,本質是一塊記憶體,如果不釋放,就會佔用記憶體,這就是為什麼open之後還要close操作。
二、遊標的優缺點:
1.優點:遊標的一個常見用途就是儲存查詢結果,以便以後使用。遊標的結果集是由SELECT語句產生,如果處理過程需要重複使用一個記錄集,那麼建立一次遊標而重複使用若干次,比重複查詢資料庫要快的多;如果我們要對查詢出的結果做特殊處理,然後在進行下一步操作(比如將資料存新表),使用遊標也是比較方便的;
2.缺點:當資料量非常大時,使用遊標會帶來很大的效率問題,因為遊標其實是相當於把磁碟資料整體放入了記憶體中,遊標資料量大的話則會造成記憶體不足;另外系統上跑的不只是一個業務,遊標使用會對行加鎖,可能影響其他業務的正常進行。所以慎用遊標
三、遊標的具體使用:
1.顯示遊標
顯示遊標的屬性,通常用來獲取一個遊標的狀態資訊
1.1、isopen(Boolean):如果遊標是開啟的,那麼這個遊標的值為true
1.2、notfound(Boolean):如果最近一次的fetch操作沒有返回一行資料,那麼此值為true
1.3、found(Boolean):如果最近一次的fetch操作返回一行資料,那麼此值為true
1.4、rowcount(Number):返回行數的總和,使用時的格式:”遊標名%rowcount“,注意不能在遊標開啟之前和遊標關閉之後使用此屬性。
顯示遊標的使用步驟:
a.定義遊標
b.開啟遊標
c.提取遊標資料
d.關閉遊標
具體使用:(從兩張表中按照一些規定抽出部分資料)
declare orgVar varchar2(30); psuhDateVar varchar2(30); memLevelVar varchar2(30); lowVar varchar2(30); validVar varchar2(30); effectiveVar varchar2(30); cursor OrgAndExpireData is select a.config_org, a.push_date, case a.mem_level when '0' then '1,2,3,4,5,6' else a.mem_level end mem_level, a.lowest_source_expire, a.is_valid, a.effective_date from integral_expire_rules a left join push_date_table b on a.config_org = b.config_org where a.is_valid = '1' and to_char(a.effective_date, 'yyyy-MM-dd') <= to_char(sysdate, 'yyyy-MM-dd') and a.push_date = to_char(sysdate, 'dd'); -- and (to_char(b.push_finish_date,'yyyy-MM')!=to_char(sysdate,'yyyy-MM') or b.push_finish_date is null); begin open OrgAndExpireData; loop fetch OrgAndExpireData into orgVar, psuhDateVar, memLevelVar, lowVar, validVar, effectiveVar; exit when OrgAndExpireData%notfound; dbms_output.put_line(orgVar || '.....' || psuhDateVar); end loop; close OrgAndExpireData; end;
2、隱式遊標
使用隱式遊標時,不需要我們手動執行open,fetch,close操作了,PL/SQL語言提供了遊標FOR迴圈語句,自動執行遊標的OPEN、FETCH、CLOSE語句和迴圈語句的功能;
隱式遊標是不需要定義的,系統預設等同為遊標的,入一個select語句,DML語句,都會開啟一個遊標。
2.1.當進入迴圈時,遊標For迴圈語句自動開啟遊標,並提取第一行遊標資料;
2.2.當程式處理完當前所提取的資料而進入下一次迴圈時,遊標FOR迴圈語句自動提取下一行資料供程式處理;
2.3.當程式處理完當前所提取的資料而進入下一次迴圈時,遊標for迴圈語句自動提取下一行資料供程式處理;
declare
cursor OrgAndExpireData is
select *
from integral_expire_rules a left join push_date_table b
on a.config_org=b.config_org
where a.is_valid='1'
and to_char(a.effective_date,'yyyy-MM-dd')<=to_char(sysdate,'yyyy-MM-dd')
and a.push_date=to_char(sysdate,'dd');
-- and (to_char(b.push_finish_date,'yyyy-MM')!=to_char(sysdate,'yyyy-MM') or b.push_finish_date is null);
begin
for storeVar in OrgAndExpireData loop
dbms_output.put_line(storeVar.rule_name||'....'||storeVar.mem_level||'..'||storeVar.is_valid);
end loop;
end;
參考部落格:
https://www.zhihu.com/question/19777435/answer/37060426
https://blog.csdn.net/haiross/article/details/42967213
補充儲存過程相關:
1.select into form 和 insert into select 的區別
1.1 insert into select
語句形式為:Insert into Table2(field1,field2,...) select value1,value2,... from Table1
或者:Insert into Table2 select * from Table1
@1要求目標表Table2必須存在,並且欄位field,field2...也必須存在
@2注意語法,不要加values,和插入一條資料的sql混了,不要寫成:
Insert into Table2(field1,field2,...) values (select value1,value2,... from Table1)
1.2 select into form
語句形式為:SELECT vale1, value2 into Table2 from Table1
要求目標表Table2不存在,因為在插入時會自動建立表Table2,並將Table1中指定欄位資料複製到Table2中
2.儲存過程中不能直接使用ddl語句,如truncate table,需要這種形式:
execute immediate 'truncate table emp';注意,引號內不能加分號