oracle:IF語句 Loop循環 Cursor的用法(一)

1 概述sql

在大多數時候咱們在設計pl-sql程序的時候都遵循下面的步驟:  
打開遊標 ->開始循環 -> 從遊標中取值->檢查那一行被返回 -> 處理 -> 關閉循環 -> 關閉遊標
oop

2 格式:複製內容到剪貼板/ 程序代碼
CURSOR <遊標名稱> IS
<遊標名稱>%ROWTYPE;
BEGIN
  OPEN <遊標名稱>
  LOOP
    FETCH <遊標名稱> INTO ;
    EXIT WHEN <遊標名稱>%NOTFOUND;

    <其它要執行的代碼>
  END LOOP;
  CLOSE <遊標名稱>;
END <存儲過程名稱>;
/
測試

3 代碼fetch

代碼例子:複製內容到剪貼板程序代碼 程序代碼
TRUNCATE TABLE loop_test;

DECLARE

CURSOR ao_cur IS
Select SUBSTR(object_name,1,5) FIRSTFIVE
FROM all_objs
Where SUBSTR(object_name,1,5) BETWEEN 'A' AND 'M';
this


ao_rec ao_cur%ROWTYPE;

BEGIN
  OPEN ao_cur;
  LOOP
    FETCH ao_cur INTO ao_rec;
    EXIT WHEN ao_cur%NOTFOUND;

    Insert INTO loop_test VALUES (ao_rec.firstfive);
  END LOOP;
  COMMIT;
  CLOSE ao_cur;
END;
/

Select COUNT(*) FROM loop_test;

[code]

Demo
[code]
Fetch Demo

Create TABLE t1 (tcol NUMBER);

Create TABLE t2 (c NUMBER);

BEGIN
  FOR i IN 1..500 LOOP
    Insert INTO t1 VALUES (i);
  END LOOP;
END;
/

Select COUNT(*) FROM t1;

COMMIT;
Create or REPLACE FUNCTION p (c_in NUMBER) RETURN NUMBER IS

PRAGMA AUTONOMOUS_TRANSACTION;

BEGIN
  -- Every time this is called, write a row to table t2
  Insert INTO t2 VALUES (c_in);
  COMMIT;
  RETURN c_in;
END p;
/
DECLARE
  BEGIN
  /* Open up a cursor for loop, also selecting
  * the "p" function which will write rows to
  * t2 for every row fetched from t1. */

  FOR crec IN (Select tcol, p(tcol) FROM t1) LOOP
    -- Break out of the loop immediately
    EXIT;
  END LOOP;
END;
/

Select COUNT(*) FROM t2;

spa



注意:%ROWTYPE也能夠用遊標名來定義,但必需要首先聲明遊標,因此上面的例子要採用顯示的遊標聲明


Cursor FOR Loop

格式:
設計

複製內容到剪貼板程序代碼 程序代碼
Create or REPLACE PROCEDURE <存儲過程名稱> IS

CURSOR <遊標名稱> IS


BEGIN
  FOR IN <遊標名稱>
  LOOP
    <其它要執行的代碼>
  END LOOP;
END <存儲過程名稱>;
/
code



代碼:it

複製內容到剪貼板程序代碼 程序代碼
TRUNCATE TABLE loop_test;

DECLARE
CURSOR ao_cur IS
   Select SUBSTR(object_name,1,5) FIRSTFIVE
   FROM all_objs
   Where SUBSTR(object_name,1,5) BETWEEN 'N' AND 'W';
BEGIN
  FOR ao_rec IN ao_cur LOOP
    Insert INTO loop_test VALUES (ao_rec.firstfive);
  END LOOP;
  COMMIT;
END;
/

Select COUNT(*) FROM loop_test;

io





Curcor For Loop是一個隱式的遊標聲明.
格式:

複製內容到剪貼板程序代碼 程序代碼
BEGIN
  FOR IN
  LOOP
    <其它要執行的代碼>
  END LOOP;
END <存儲過程名稱>;
/



Demo

複製內容到剪貼板程序代碼 程序代碼
TRUNCATE TABLE loop_test;

BEGIN
  FOR ao_rec IN (
    Select SUBSTR(object_name,1,5) FIRSTFIVE
    FROM all_objs
    Where SUBSTR(object_name,1,5) BETWEEN 'N' AND 'Z')
  LOOP
    Insert INTO loop_test VALUES (ao_rec.firstfive);
  END LOOP;
  COMMIT;
END;
/

Select COUNT(*) FROM loop_test;




Cursor Loop With Where CURRENT OF Clause

格式:

複製內容到剪貼板程序代碼 程序代碼
Create or REPLACE PROCEDURE <存儲過程名稱> IS



BEGIN
  FOR IN (<遊標名稱>)
  LOOP
    <其它要執行的代碼>
    Update
    SET =
    Where CURRENT OF <遊標名稱>
  END LOOP;
END <存儲過程名稱>;
/




Demo:

複製內容到剪貼板程序代碼 程序代碼     
Create TABLE test (
pid  NUMBER(3),
cash  NUMBER(10,2));

Insert INTO test VALUES (100, 10000.73);
Insert INTO test VALUES (200  25000.26);
Insert INTO test VALUES (300, 30000.11);
Insert INTO test VALUES (400, 45000.99);
Insert INTO test VALUES (500, 50000.08);
COMMIT;
Create or REPLACE PROCEDURE wco IS

CURSOR x_cur IS
Select pid, cash
FROM test
Where cash < 35000
FOR Update;

BEGIN
  FOR x_rec IN x_cur LOOP
    Update test
    SET cash = FLOOR(cash)
    Where CURRENT OF x_cur;
  END LOOP;
  COMMIT;
END wco;
/
exec wco;

Select * FROM test;


嵌套的遊標循環 Nested Cursor Loops

測試樣表

複製內容到剪貼板程序代碼 程序代碼     
Create TABLE airplanes (
program_id  VARCHAR2(3),
line_number NUMBER(10),
customer_id VARCHAR2(4),
order_date  DATE,
delivered_date DATE)
PCTFREE 0;

Create INDEX programid_idx
ON airplanes (program_id)
PCTFREE 0;

Create TABLE parts (
program_id VARCHAR2(3),
line_type VARCHAR2(4),
part_type VARCHAR2(10),
quantity NUMBER(3));

Create TABLE ap_parts AS
Select a.customer_id, p.part_type, p.quantity
FROM airplanes a, parts p
Where a.program_id = p.program_id
AND 1=2;



PL-SQL Example

複製內容到剪貼板程序代碼 程序代碼     
DECLARE
progid  airplanes.program_id%TYPE;
lineno  airplanes.line_number%TYPE;
custid  airplanes.customer_id%TYPE := 'AAL';
orddate airplanes.order_date%TYPE;
deldate airplanes.delivered_date%TYPE;
BEGIN
  FOR i IN 1 .. 5 LOOP
    Select DECODE(i, 1, '737', 2, '747', 3, '757', 4, '767', 5, '777')
    INTO progid
    FROM dual;

    FOR lineno IN 1..250 LOOP
      Select DECODE(custid, 'AAL','DAL','DAL','SAL','SAL','ILC',
     'ILC','SWA', 'SWA','NWO','NWO','AAL')
      INTO custid
      FROM dual;

    IF progid = '737' THEN
      ordDate := SYSDATE + lineno;
      DelDate := ordDate + lineno + 100;
    ELSIF progid = '747' THEN
      ordDate := SYSDATE + lineno+17;
      DelDate := ordDate + lineno + 302;
    ELSIF progid = '757' THEN
      ordDate := SYSDATE + lineno+22;
      DelDate := ordDate + lineno + 202;
    ELSIF progid = '767' THEN
      ordDate := SYSDATE + lineno+43;
      DelDate := ordDate + lineno + 189;
    ELSIF progid = '777' THEN
      ordDate := SYSDATE + lineno-69;
      DelDate := ordDate + lineno + 299;
    END IF;

      Insert INTO airplanes
      (program_id, line_number, customer_id, order_date,
       delivered_date)
      VALUES
      (progid, lineno, custid, orddate, deldate);
    END LOOP;
  END LOOP;
  COMMIT;
END load_airplanes;
/



複製內容到剪貼板程序代碼 程序代碼
Load Airplane Parts    BEGIN
  Insert INTO parts VALUES ('737', 'Even', 'Wing', 2);
  Insert INTO parts VALUES ('747', 'Even', 'Wing', 2);
  Insert INTO parts VALUES ('757', 'Even', 'Wing', 2);
  Insert INTO parts VALUES ('767', 'EVen', 'Wing', 2);
  Insert INTO parts VALUES ('777', 'even', 'Wing', 2);
  Insert INTO parts VALUES ('737', 'ODD', 'Wing', 2);
  Insert INTO parts VALUES ('747', 'odd', 'Wing', 2);
  Insert INTO parts VALUES ('757', 'Odd', 'Wing', 2);
  Insert INTO parts VALUES ('767', 'Odd', 'Wing', 2);
  Insert INTO parts VALUES ('777', 'Odd', 'Wing', 2);
  Insert INTO parts VALUES ('737', 'Even', 'Galley', 1);
  Insert INTO parts VALUES ('747', 'EVen', 'Galley', 3);
  Insert INTO parts VALUES ('757', 'EVEN', 'Galley', 3);
  Insert INTO parts VALUES ('767', 'EVeN', 'Galley', 2);
  Insert INTO parts VALUES ('777', 'even', 'Galley', 3);
  Insert INTO parts VALUES ('737', 'ODD', 'Galley', 2);
  Insert INTO parts VALUES ('747', 'odd', 'Galley', 4);
  Insert INTO parts VALUES ('757', 'Odd', 'Galley', 3);
  Insert INTO parts VALUES ('767', 'ODd', 'Galley', 4);
  Insert INTO parts VALUES ('777', 'odD', 'Galley', 4);
  Insert INTO parts VALUES ('737', 'Even', 'Tire', 10);
  Insert INTO parts VALUES ('747', 'Even', 'Tire', 18);
  Insert INTO parts VALUES ('757', 'Even', 'Tire', 12);
  Insert INTO parts VALUES ('767', 'Even', 'Tire', 14);
  Insert INTO parts VALUES ('777', 'EveN', 'Tire', 16);
  Insert INTO parts VALUES ('737', 'ODD', 'Tire', 14);
  Insert INTO parts VALUES ('747', 'Odd', 'Tire', 20);
  Insert INTO parts VALUES ('757', 'Odd', 'Tire', 14);
  Insert INTO parts VALUES ('767', 'Odd', 'Tire', 16);
  Insert INTO parts VALUES ('777', 'Odd', 'Tire', 18);
  Insert INTO parts VALUES ('737', 'Even', 'Seats', 105);
  Insert INTO parts VALUES ('747', 'Even', 'Seats', 255);
  Insert INTO parts VALUES ('757', 'Even', 'Seats', 140);
  Insert INTO parts VALUES ('767', 'Even', 'Seats', 200);
  Insert INTO parts VALUES ('777', 'EveN', 'Seats', 210);
  Insert INTO parts VALUES ('737', 'ODD', 'Seats', 137);
  Insert INTO parts VALUES ('747', 'Odd', 'Seats', 20);
  Insert INTO parts VALUES ('757', 'Odd', 'Seats', 166);
  Insert INTO parts VALUES ('767', 'Odd', 'Seats', 345);
  Insert INTO parts VALUES ('777', 'Odd', 'Seats', 267);
  COMMIT;
END;
/
[code]


嵌套固定的遊標

Nested Loops With Static Cursors

DeMo:
[code]    

Create or REPLACE PROCEDURE nested_loop IS

CURSOR a_cur IS
Select program_id, line_number, customer_id
FROM airplanes;

a_rec a_cur%ROWTYPE;

CURSOR p_cur IS
Select part_type, quantity
FROM parts
Where program_id = a_rec.program_id
AND UPPER(line_type)=DECODE(MOD(a_rec.line_number,2),0,'EVEN','ODD');

p_rec p_cur%ROWTYPE;

BEGIN
  OPEN a_cur;
  LOOP
    FETCH a_cur INTO a_rec;
    EXIT WHEN a_cur%NOTFOUND;

    OPEN p_cur;
    LOOP
      FETCH p_cur INTO p_rec;
      EXIT WHEN p_cur%NOTFOUND;
      Insert INTO ap_parts
      (customer_id, part_type, quantity)
      VALUES
      (a_rec.customer_id, p_rec.part_type, p_rec.quantity);
    END LOOP;
    CLOSE p_cur;

  END LOOP;
  COMMIT;
  CLOSE a_cur;
END nested_loop;
/



嵌套使用BLUK COLLECT獲取數據集的循環

Nested Loops with Bulk Collect



這個demo是爲了顯示經過BULK COLLECTION來複制嵌套循環中的遊標裏的數據

Demo

複製內容到剪貼板程序代碼 程序代碼 Create or REPLACE PROCEDURE bulk_nested IS CURSOR a_cur ISSelect program_id, line_number, customer_idFROM airplanes;TYPE ap_array IS TABLE OF airplanes.program_id%TYPEINDEX BY BINARY_INTEGER;ap_rec ap_array;TYPE al_array IS TABLE OF airplanes.line_number%TYPEINDEX BY BINARY_INTEGER;al_rec al_array;TYPE ac_array IS TABLE OF airplanes.customer_id%TYPEINDEX BY BINARY_INTEGER;ac_rec ac_array;TYPE pp_array IS TABLE OF parts.part_type%TYPEINDEX BY BINARY_INTEGER;pp_rec pp_array;TYPE pq_array IS TABLE OF parts.quantity%TYPEINDEX BY BINARY_INTEGER;pq_rec pq_array; BEGIN  OPEN a_cur;  LOOP    FETCH a_cur BULK COLLECT INTO ap_rec, al_rec, ac_rec LIMIT 500;    FOR i IN 1 .. ap_rec.COUNT LOOP      DECLARE        CURSOR p_cur IS        Select part_type, quantity        FROM parts        Where program_id = ap_rec(i)        AND UPPER(line_type)=DECODE(MOD(al_rec(i),2),0,'EVEN','ODD');      BEGIN         OPEN p_cur;        LOOP          FETCH p_cur BULK COLLECT INTO pp_rec, pq_rec;          FORALL j IN pp_rec.FIRST .. pp_rec.LAST          Insert INTO ap_parts          (customer_id, part_type, quantity)          VALUES          (ap_rec(i), pp_rec(j), pq_rec(j));          EXIT WHEN p_cur%NOTFOUND;        END LOOP;         CLOSE p_cur;      END;    END LOOP;    EXIT WHEN a_cur%NOTFOUND;  END LOOP;  COMMIT;  CLOSE a_cur;END bulk_nested;/

相關文章
相關標籤/搜索