๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป/ORACLE

(29)[ORACLE] 12์ผ์ฐจ : PL/SQL - 3 (์ปค์„œ์™€ ๋™์ ์ฟผ๋ฆฌ)

by ๋”ฐ๊ถˆ 2024. 3. 26.

 

 

์ปค์„œ(Cursor)๋ž€?
ํ•˜๋‚˜์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ ๋ ˆ์ฝ”๋“œ๋กœ ๊ตฌ์„ฑ๋œ ์ž‘์—…์˜์—ญ์—์„œ SQL๋ฌธ์„
์‹คํ–‰ํ•˜๊ณ  ๊ทธ ๊ณผ์ •์— ์ƒ๊ธด ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ CURSOR๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์˜ค๋ผํด ์„œ๋ฒ„์— ์˜ํ•ด ์‹คํ–‰๋˜๋Š” ๋ชจ๋“  SQL๋ฌธ์€ ์—ฐ๊ด€๋œ ๊ฐ๊ฐ์˜ ์ปค์„œ๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋‹ค.

์ปค์„œ์˜ ์ข…๋ฅ˜
์•”์‹œ์  ์ปค์„œ : ๋ชจ๋“  DML๊ณผ PL/SQL SELECT๋ฌธ์— ๋Œ€ํ•ด ์„ ์–ธ๋œ๋‹ค.
๋ช…์‹œ์  ์ปค์„œ : ํ”„๋กœ๊ทธ๋ž˜๋จธ์— ์˜ํ•ด ์„ ์–ธ๋˜๋ฉฐ ์ด๋ฆ„์ด ์žˆ๋Š” ์ปค์„œ.




์•”์‹œ์  ์ปค์„œ

์•”์‹œ์ ์ธ ์ปค์„œ๋Š” ์˜ค๋ผํด์ด๋‚˜ PL/SQL์‹คํ–‰ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜๋Š” SQL๋ฌธ์žฅ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๊ณณ์— ๋Œ€ํ•œ ์ต๋ช…์˜ ์ฃผ์†Œ. ์˜ค๋ผํด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์‹คํ–‰๋˜๋Š” ๋ชจ๋“  ๋ฌธ์žฅ์€ ์•”์‹œ์ ์ธ ์ปค์„œ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, ์ปค์„œ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์•”์‹œ์  ์ปค์„œ๋Š”  SQL ๋ฌธ์ด ์‹คํ–‰๋˜๋Š” ์ˆœ๊ฐ„ ์ž๋™์œผ๋กœ OPEN๊ณผ CLOSE๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 

--์ปค์„œ์˜ ์ข…๋ฅ˜--
SQL%ROWCOUNT : ํ•ด๋‹น SQL ๋ฌธ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ–‰์˜ ์ˆ˜
SQL%FOUND : ํ•ด๋‹น SQL ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ–‰์˜ ์ˆ˜๊ฐ€ 1๊ฐœ ์ด์ƒ์ผ ๊ฒฝ์šฐ TRUE
SQL%NOTFOUND : ํ•ด๋‹น SQL ๋ฌธ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ–‰์˜ ์ˆ˜๊ฐ€ ์—†์„ ๊ฒฝ์šฐ TRUE
SQL%ISOPEN : ํ•ญ์ƒ FALSE, ์•”์‹œ์  ์ปค์„œ๊ฐ€ ์—ด๋ ค ์žˆ๋Š”์ง€์˜ ์—ฌ๋ถ€ ๊ฒ€์ƒ‰

 

--0 ๋ ˆ์ฝ”๋“œ ์‚ญ์ œ
DECLARE
    vempNO emp.empNo%TYPE;
    vcount  NUMBER;
BEGIN    
    vempNo := '100l';
    DELETE FROM emp WHERE empNo = vempNo;
    vcount := SQL%ROWCOUNT;
    COMMIT;
    
    DBMS_OUTPUT.PUT_LINE(vcount||' ๋ ˆ์ฝ”๋“œ ์‚ญ์ œ');
END;
/

 

 

 

๋ช…์‹œ์  ์ปค์„œ

๋ช…์‹œ์  ์ปค์„œ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ์— ์˜ํ•ด ์„ ์–ธ๋˜๋ฉฐ ์ด๋ฆ„์ด ์žˆ๋Š” ์ปค์„œ๋กœ ์—ฌ๋Ÿฌ row๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. 

CURSOR ์„ ์–ธ → ์ปค์„œ OPEN → FETCH → ์ปค์„œ CLOSE

  • CURSOR์„ ์–ธ : ๊ฒ€์ƒ‰ํ•  ์ฟผ๋ฆฌ๋ฅผ ์„ ์–ธํ•œ๋‹ค.
  • ์ปค์„œ OPEN : OPEN์€ ์ปค์„œ์—์„œ ์„ ์–ธ๋œ SELECT๋ฌธ์˜ ์‹คํ–‰์„ ์˜๋ฏธํ•œ๋‹ค. ๋ฐ์ดํ„ฐํ–‰์„ ์ถ”์ถœํ•˜์ง€ ๋ชปํ•ด๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. 
  • FETCH : ์ปค์„œ์˜ FETCH๋Š” ํ˜„์žฌ ๋ฐ์ดํ„ฐ ํ–‰์„ OUTPUT๋ณ€์ˆ˜์— ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ปค์„œ์˜ SELECT๋ฌธ ์ปฌ๋Ÿผ์˜ ์ˆ˜ ๋ฐ ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ OUTPUT๋ณ€์ˆ˜์˜ ์ˆ˜ ๋ฐ ๋ฐ์ดํ„ฐ ํƒ€์ž…๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค. 
  • ์ปค์„œ CLOSE : OPEN๋œ ์ปค์„œ๋Š” ์‚ฌ์šฉ ์™„๋ฃŒํ›„ ๋ฐ˜๋“œ์‹œ CLOSE ํ•ด์•ผ ํ•œ๋‹ค. ์„ ์–ธ๋œ SELECT๋ฌธ์˜ ์„ ์–ธ์„ ํ•ด์ œ ํ•œ๋‹ค. ์ปค์„œ๊ฐ€ ๋œ CLOSE๋œ ์ƒํƒœ์—์„œ๋Š” FETCH๋ฅผ ํ•  ์ˆ˜ ์—†๋‹ค. 
-- name,sal ์ „์ฒด ๊ฐ€์ ธ์˜ค๊ธฐ 
DECLARE
        vname emp.name%TYPE;
        vsal    emp.sal%TYPE;
        --CURSOR ์„ ์–ธ
        CURSOR cur_emp IS SELECT name,sal FROM emp;
        
BEGIN   
        --CURSOR OPEN 
        OPEN cur_emp;
        
        LOOP
            --FETCH
            FETCH cur_emp INTO vname,vsal;
            EXIT WHEN cur_emp%NOTFOUND;
            
            DBMS_OUTPUT.PUT_LINE(vname||':'||vsal);
        END LOOP;
            --CLOSE
        CLOSE cur_emp;
END;
/

 

-- '๊น€'์”จ ์„ฑ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ ๊ฒ€์ƒ‰

CREATE OR REPLACE PROCEDURE pEmpSelect
(
    pName VARCHAR2
)
IS
    vname emp.name%TYPE;
    vsal    emp.sal%TYPE;
    
    
    CURSOR cur_emp IS
            SELECT name,sal FROM emp WHERE INSTR(name,pName)>0;
BEGIN   
        
        OPEN cur_emp;
        
        LOOP
            --FETCH
            FETCH cur_emp INTO vname,vsal;
            EXIT WHEN cur_emp%NOTFOUND;
            
            DBMS_OUTPUT.PUT_LINE(vname||':'||vsal);
        END LOOP;
            --CLOSE
        CLOSE cur_emp;
END;
/

EXEC pEmpSelect('๊น€');

 

 

 

์ปค์„œ ๋ณ€์ˆ˜

๋ช…์‹œ์  ์ปค์„œ์™€ ์•”์‹œ์  ์ปค์„œ๋Š” ์ •์ ์ด๋ฏ€๋กœ, ์ปค์„œ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ์‹œ์ ์—์„œ ์ฟผ๋ฆฌ๋ฌธ์ด ์ •์˜๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋Ÿฐํƒ€์ž„๊นŒ์ง€ ์ปค์„œ์— ์ด์šฉํ•  ์ฟผ๋ฆฌ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— REF CURSOR์™€ ์ปค์„œ๋ณ€์ˆ˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๋Ÿฐํƒ€์ž„์‹œ์— ์ปค์„œ์˜ ์ฟผ๋ฆฌ๋ฅผ ์ •์˜ํ•˜๊ณ  ๊ฒฐ๊ณผ ์…‹์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์žˆ๋‹ค.

 

-- SYS_REFCURSOR
-- : ์•ฝํ•œ ์ฐธ์กฐ ์ปค์„œ ํƒ€์ž…
-- : ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๊ฒฐ๊ณผ ์…‹์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Œ
-- : ํ”„๋กœ์‹œ์ € ์‹คํ–‰๊ฒฐ๊ณผ(SELECT ๋ฌธ)๋ฅผ ์ž๋ฐ” ๋“ฑ ํ”„๋กœ๊ทธ๋žจ์— ์ „๋‹ฌ ํ• ๋•Œ ์‚ฌ์šฉ

-- ์ปค์„œ ๋ณ€์ˆ˜ ์„ ์–ธ
์ปค์„œ๋ณ€์ˆ˜ SYS_REFCURSOR;

-- ์ปค์„œ ๋ณ€์ˆ˜ ์‚ฌ์šฉ
OPEN ์ปค์„œ๋ณ€์ˆ˜ FOR SELECT ๋ฌธ

-- ์ปค์„œ ๋ณ€์ˆ˜์—์„œ ๊ฐ’ ๊ฐ€์ ธ ์˜ค๊ธฐ
FETCH ์ปค์„œ๋ณ€์ˆ˜ INTO ๋ณ€์ˆ˜, ๋ณ€์ˆ˜;
FETCH ์ปค์„œ๋ณ€์ˆ˜ INTO ๋ ˆ์ฝ”๋“œ๋ณ€์ˆ˜;

 

--SYS_REFCURSOR


CREATE OR REPLACE PROCEDURE pEmpSelect
(
        pName VARCHAR2,
        pResult OUT SYS_REFCURSOR
)
IS      
BEGIN   
    OPEN pResult FOR
        SELECT name,sal FROM emp WHERE INSTR(name,pName)>0;
END;
/

 

--ํ™•์ธ

DECLARE
        vName emp.name%TYPE;
        vSal    emp.sal%TYPE;
        vResult SYS_REFCURSOR;
BEGIN
        pEmpSelect('์ •',vResult);
        
        LOOP
            FETCH vResult INTO vName,vSal;
            EXIT WHEN vResult%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE(vName||':'||vSal);
        END LOOP;
END;
/

 

 


 

 

๋™์ ์ฟผ๋ฆฌ๋ž€?
ํ”„๋กœ์‹œ์ €๋“ฑ์—์„œ ๋™์ ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ํ…์ŠคํŠธ ์ฟผ๋ฆฌ๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ

-- EXECUTE IMMEDIATE
-- : DDL, DML ๊ตฌ๋ฌธ์„ ์‹คํ–‰
-- : SELECT ๊ตฌ๋ฌธ ์‹คํ–‰ ์‹œ INTO ์ ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ๊ฐ’์„ ๋ฐ˜ํ™˜ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ
-- : ํ”„๋กœ์‹œ์ € ๋“ฑ์—์„œ ๋™์ ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ํ…์ŠคํŠธ ์ฟผ๋ฆฌ๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ
-- : RESOURCE ๊ถŒํ•œ๋งŒ ์žˆ์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ…Œ์ด๋ธ”์ƒ์„ฑ, ์‹œํ€€์Šค ์ƒ์„ฑ๋“ฑ์„ ํ• ์ˆ˜ ์žˆ์ง€๋งŒ
-- : EXECUTE IMMEDIATE ์—์„œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
-- : EXECUTE IMMEDIATE ๋กœ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์‹œํ€€์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์˜ ์‹œ์Šคํ…œ ๊ถŒํ•œ์ด ํ•„์š” ํ•œ๋‹ค.

 

 

 CREATE OR REPLACE PROCEDURE pboardcreate
     (
        pname VARCHAR2
     )
     IS
        S VARCHAR2(4000);
     BEGIN
        S := ' create table ' || pname;
        S := S|| '(num NUMBER PRIMARY KEY, ';
        S := S|| ' name VARCHAR2(30) not null, ';
        S := S|| ' subiect VARCHAR2(255) not null, ';
        S := S|| ' content VARCHAR2(4000) not null, ';
        S := S|| ' hitCount NUMBER DEFAULT 0, ';
        S := S|| ' reg_date DATE DEFAULT SYSDATE) ';
        
        FOR T IN (SELECT tname FROM TAB WHERE tname = UPPER(pname))LOOP
            EXECUTE IMMEDIATE 'drop table ' || pname || ' PURGE';
            Dbms_Output.Put_Line(Pname||'ํ…Œ์ด๋ธ” ์‚ญ์ œ...');
        END LOOP;
        
        EXECUTE IMMEDIATE S;
        Dbms_Output.Put_Line(Pname||'ํ…Œ์ด๋ธ” ์ƒ์„ฑ...');
        
        S := 'CREATE SEQUENCE ' ||pname||'_seq';
        FOR T IN ( SELECT * FROM seq WHERE sequence_name = UPPER(pname||'_seq'))LOOP
            EXECUTE IMMEDIATE 'DROP SEQUENCE '||pname||'_seq';
            DBMS_OUTPUT.PUT_LINE(PNAME||'_seq ์‹œํ€€์Šค ์‚ญ์ œ...');
        END LOOP;
        
        EXECUTE IMMEDIATE S;
        DBMS_OUTPUT.PUT_LINE(PNAME||'_seq ์‹œํ€€์Šค ์ƒ์„ฑ...');
END;
/ 
     

SELECT * FROM TAB;

EXEC pboardcreate('board');
SELECT * FROM TAB;
SELECT * FROM seq;