1. 程式人生 > >資料庫遊標學習記錄

資料庫遊標學習記錄

一、遊標的定義:遊標是一個容器,用來記錄查詢結果集的,本質是一塊記憶體,如果不釋放,就會佔用記憶體,這就是為什麼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';注意,引號內不能加分號