Search
Duplicate

ν”„λ‘œμ‹œμ €

ν”„λ‘œμ‹œμ €(Procedure)

νŠΉμ • 업무λ₯Ό μ²˜λ¦¬ν•˜λŠ” 일련의 μž‘μ—…μ„ ν”„λ‘œκ·Έλž¨μœΌλ‘œ μ €μž₯ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 객체
ν•¨μˆ˜μ™€ 달리 값을 λ°˜ν™˜ν•˜μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€.

ν•¨μˆ˜ vs ν”„λ‘œμ‹œμ € 비ꡐ

ꡬ뢄
ν•¨μˆ˜(Function)
ν”„λ‘œμ‹œμ €(Procedure)
λ°˜ν™˜κ°’
λ°˜λ“œμ‹œ ν•˜λ‚˜μ˜ 값을 λ°˜ν™˜
λ°˜ν™˜κ°’μ΄ μ—†κ±°λ‚˜ μ—¬λŸ¬ 개 κ°€λŠ₯
μ‹€ν–‰ 방법
SELECT λ¬Έμ—μ„œ 직접 호좜 κ°€λŠ₯
EXECUTE 문으둜 호좜
μ£Ό μš©λ„
계산 κ²°κ³Ό λ°˜ν™˜
λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 처리
DML μ‚¬μš©
μ œν•œμ 
자유둭게 μ‚¬μš© κ°€λŠ₯

ν”„λ‘œμ‹œμ € 생성

β€’
νŒŒλΌλ―Έν„° μ—†λŠ” ν”„λ‘œμ‹œμ €
CREATE OR REPLACE PROCEDURE ν”„λ‘œμ‹œμ €λͺ… IS | AS μ„ μ–ΈλΆ€ BEGIN μ‹€ν–‰λΆ€ EXCEPTION μ˜ˆμ™Έ μ²˜λ¦¬λΆ€ END [ν”„λ‘œμ‹œμ €λͺ…];
SQL
볡사
β€’
νŒŒλΌλ―Έν„° μžˆλŠ” ν”„λ‘œμ‹œμ €
CREATE OR REPLACE PROCEDURE ν”„λ‘œμ‹œμ €λͺ… ( νŒŒλΌλ―Έν„°1 [IN / OUT / IN OUT] λ°μ΄ν„°νƒ€μž… [ := κ°’ | DEFAULT κΈ°λ³Έκ°’ ], νŒŒλΌλ―Έν„°2 [IN / OUT / IN OUT] λ°μ΄ν„°νƒ€μž… [ := κ°’ | DEFAULT κΈ°λ³Έκ°’ ], ... ) IS | AS μ„ μ–ΈλΆ€ BEGIN μ‹€ν–‰λΆ€ EXCEPTION μ˜ˆμ™Έ μ²˜λ¦¬λΆ€ END [ν”„λ‘œμ‹œμ €λͺ…];
SQL
볡사

νŒŒλΌλ―Έν„° λͺ¨λ“œ

λͺ¨λ“œ
μ„€λͺ…
데이터 흐름
κΈ°λ³Έκ°’ μ„€μ •
IN
μž…λ ₯ μ „μš© νŒŒλΌλ―Έν„°
ν˜ΈμΆœλΆ€ β†’ ν”„λ‘œμ‹œμ €
κ°€λŠ₯
OUT
좜λ ₯ μ „μš© νŒŒλΌλ―Έν„°
ν”„λ‘œμ‹œμ € β†’ ν˜ΈμΆœλΆ€
λΆˆκ°€λŠ₯
IN OUT
μž…μΆœλ ₯ νŒŒλΌλ―Έν„°
μ–‘λ°©ν–₯ (ν˜ΈμΆœλΆ€ ν”„λ‘œμ‹œμ €)
κ°€λŠ₯
IN λͺ¨λ“œ (μž…λ ₯ νŒŒλΌλ―Έν„°)
β€’
ν”„λ‘œμ‹œμ €λ‘œ 값을 μ „λ‹¬λ§Œ ν•˜λŠ” νŒŒλΌλ―Έν„°μž…λ‹ˆλ‹€.
β€’
ν”„λ‘œμ‹œμ € λ‚΄λΆ€μ—μ„œ 값을 λ³€κ²½ν•  수 μ—†μŠ΅λ‹ˆλ‹€ (읽기 μ „μš©).
β€’
기본값을 μ„€μ •ν•  수 있으며, μƒλž΅ μ‹œ κΈ°λ³Έ λͺ¨λ“œμž…λ‹ˆλ‹€.
β€’
λ¦¬ν„°λŸ΄, λ³€μˆ˜, μˆ˜μ‹ 등을 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.
OUT λͺ¨λ“œ (좜λ ₯ νŒŒλΌλ―Έν„°)
β€’
ν”„λ‘œμ‹œμ €μ—μ„œ ν˜ΈμΆœλΆ€λ‘œ 값을 λ°˜ν™˜ν•˜λŠ” νŒŒλΌλ―Έν„°μž…λ‹ˆλ‹€.
β€’
ν”„λ‘œμ‹œμ € λ‚΄λΆ€μ—μ„œ 값을 ν• λ‹Ήν•΄μ•Ό ν•©λ‹ˆλ‹€.
β€’
호좜 μ‹œ λ°˜λ“œμ‹œ λ³€μˆ˜λ₯Ό 전달해야 ν•©λ‹ˆλ‹€ (λ¦¬ν„°λŸ΄ λΆˆκ°€).
β€’
기본값을 μ„€μ •ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
β€’
ν”„λ‘œμ‹œμ € μ‹œμž‘ μ‹œ μžλ™μœΌλ‘œ NULL둜 μ΄ˆκΈ°ν™”λ©λ‹ˆλ‹€.
IN OUT λͺ¨λ“œ (μž…μΆœλ ₯ νŒŒλΌλ―Έν„°)
β€’
ν”„λ‘œμ‹œμ €λ‘œ 값을 μ „λ‹¬ν•˜κ³ , λ‹€μ‹œ κ²°κ³Όλ₯Ό λ°›μ•„μ˜€λŠ” νŒŒλΌλ―Έν„°μž…λ‹ˆλ‹€.
β€’
ν”„λ‘œμ‹œμ € λ‚΄λΆ€μ—μ„œ 값을 읽고 μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
β€’
호좜 μ‹œ λ°˜λ“œμ‹œ λ³€μˆ˜λ₯Ό 전달해야 ν•©λ‹ˆλ‹€.
β€’
기본값을 μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
β€’
값을 λˆ„μ ν•˜κ±°λ‚˜ λ³€ν™˜ν•˜λŠ” μž‘μ—…μ— μœ μš©ν•©λ‹ˆλ‹€.

ν”„λ‘œμ‹œμ € 생성 μ˜ˆμ‹œ

β€’
νŒŒλΌλ―Έν„° μ—†λŠ” ν”„λ‘œμ‹œμ €
β€’
νŒŒλΌλ―Έν„° μžˆλŠ” ν”„λ‘œμ‹œμ €
β€’
νŒŒλΌλ―Έν„° μ—†λŠ” ν”„λ‘œμ‹œμ €
CREATE OR REPLACE PROCEDURE update_all_salaries IS v_count NUMBER := 0; BEGIN UPDATE employees SET salary = salary * 1.05; -- μ „ 직원 5% 인상 v_count := SQL%ROWCOUNT; -- 영ν–₯받은 ν–‰ 수 COMMIT; DBMS_OUTPUT.PUT_LINE(v_count || 'λͺ…μ˜ κΈ‰μ—¬κ°€ μΈμƒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.'); EXCEPTION WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('였λ₯˜ λ°œμƒ: ' || SQLERRM); END update_all_salaries; /
SQL
볡사
β€’
νŒŒλΌλ―Έν„° μžˆλŠ” ν”„λ‘œμ‹œμ €
νŒŒλΌλ―Έν„° λͺ¨λ“œμ—λŠ” IN, OUT, IN OUT μ„Έ κ°€μ§€κ°€ μžˆμŠ΅λ‹ˆλ‹€.
CREATE OR REPLACE PROCEDURE get_emp_info ( p_emp_id IN NUMBER, -- μž…λ ₯ νŒŒλΌλ―Έν„° p_emp_name OUT VARCHAR2, -- 좜λ ₯ νŒŒλΌλ―Έν„° p_salary OUT NUMBER, -- 좜λ ₯ νŒŒλΌλ―Έν„° p_dept_name OUT VARCHAR2 -- 좜λ ₯ νŒŒλΌλ―Έν„° ) IS BEGIN SELECT e.emp_name, e.salary, d.dept_title INTO p_emp_name, p_salary, p_dept_name FROM employees e LEFT JOIN departments d ON e.dept_code = d.dept_id WHERE e.emp_id = p_emp_id; EXCEPTION WHEN NO_DATA_FOUND THEN p_emp_name := '데이터 μ—†μŒ'; p_salary := 0; p_dept_name := 'λΆ€μ„œ μ—†μŒ'; END get_emp_info; /
SQL
볡사

ν”„λ‘œμ‹œμ € 생성 (κΈ°λ³Έκ°’ μ„€μ •)

CREATE OR REPLACE PROCEDURE increase_salary ( p_emp_id IN NUMBER, p_rate IN NUMBER := 0.1, -- κΈ°λ³Έκ°’ 10% p_bonus IN NUMBER DEFAULT 0 -- κΈ°λ³Έκ°’ 0 ) IS BEGIN UPDATE employees SET salary = salary * (1 + p_rate), bonus = p_bonus WHERE emp_id = p_emp_id; COMMIT; DBMS_OUTPUT.PUT_LINE('κΈ‰μ—¬κ°€ μΈμƒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.'); END increase_salary; /
SQL
볡사

ν”„λ‘œμ‹œμ € μ‹€ν–‰

방법 1: EXECUTE λ¬Έ μ‚¬μš©

β€’
νŒŒλΌλ―Έν„°κ°€ μ—†κ°€λ‚˜ IN νŒŒλΌλ―Έν„°λ§Œ μžˆλŠ” 경우
EXECUTE ν”„λ‘œμ‹œμ €λͺ…; EXECUTE ν”„λ‘œμ‹œμ €λͺ…(인자1, 인자2, ...); EXECUTE ν”„λ‘œμ‹œμ €λͺ…(νŒŒλΌλ―Έν„°1 => 인자1, νŒŒλΌλ―Έν„°2 => 인자2, ...);
SQL
볡사
β€’
μ˜ˆμ‹œ
SET SERVEROUTPUT ON; -- νŒŒλΌλ―Έν„° μ—†λŠ” ν”„λ‘œμ‹œμ € EXECUTE update_all_salaries; -- νŒŒλΌλ―Έν„° μžˆλŠ” ν”„λ‘œμ‹œμ € (μœ„μΉ˜ 기반) EXECUTE increase_salary(100, 0.15, 0.2); -- νŒŒλΌλ―Έν„° μžˆλŠ” ν”„λ‘œμ‹œμ € (이름 기반) EXECUTE increase_salary(p_emp_id => 100, p_rate => 0.15);
SQL
볡사

방법 2: PL/SQL 블둝 λ‚΄μ—μ„œ μ‹€ν–‰

β€’
OUT νŒŒλΌλ―Έν„°κ°€ μžˆλŠ” 경우
DECLARE λ³€μˆ˜1 λ°μ΄ν„°νƒ€μž…; λ³€μˆ˜2 λ°μ΄ν„°νƒ€μž…; ... BEGIN ν”„λ‘œμ‹œμ €λͺ…(INνŒŒλΌλ―Έν„°, OUTλ³€μˆ˜1, OUTλ³€μˆ˜2, ...); -- λ°˜ν™˜λœ κ°’ μ‚¬μš© DBMS_OUTPUT.PUT_LINE(λ³€μˆ˜1); DBMS_OUTPUT.PUT_LINE(λ³€μˆ˜2); END; /
SQL
볡사
β€’
μ˜ˆμ‹œ
DECLARE v_name VARCHAR2(50); v_sal NUMBER; v_dept VARCHAR2(50); BEGIN get_emp_info(100, v_name, v_sal, v_dept); DBMS_OUTPUT.PUT_LINE('이름: ' || v_name); DBMS_OUTPUT.PUT_LINE('κΈ‰μ—¬: ' || v_sal); DBMS_OUTPUT.PUT_LINE('λΆ€μ„œ: ' || v_dept); END; /
SQL
볡사

ν”„λ‘œμ‹œμ € μ‚­μ œ

DROP PROCEDURE ν”„λ‘œμ‹œμ €λͺ…;
SQL
볡사
β€’
μ˜ˆμ‹œ
DROP PROCEDURE update_all_salaries;
SQL
볡사

μ‹€μ „ 예제

예제 1: λΆ€μ„œλ³„ κΈ‰μ—¬ 톡계 ν”„λ‘œμ‹œμ €

CREATE OR REPLACE PROCEDURE get_dept_salary_stats ( p_dept_code IN VARCHAR2, p_avg_sal OUT NUMBER, p_max_sal OUT NUMBER, p_min_sal OUT NUMBER, p_emp_count OUT NUMBER ) IS BEGIN SELECT AVG(salary), MAX(salary), MIN(salary), COUNT(*) INTO p_avg_sal, p_max_sal, p_min_sal, p_emp_count FROM employees WHERE dept_code = p_dept_code; DBMS_OUTPUT.PUT_LINE('=== λΆ€μ„œ κΈ‰μ—¬ 톡계 ==='); DBMS_OUTPUT.PUT_LINE('평균 κΈ‰μ—¬: ' || TO_CHAR(p_avg_sal, '999,999,999')); DBMS_OUTPUT.PUT_LINE('졜고 κΈ‰μ—¬: ' || TO_CHAR(p_max_sal, '999,999,999')); DBMS_OUTPUT.PUT_LINE('μ΅œμ € κΈ‰μ—¬: ' || TO_CHAR(p_min_sal, '999,999,999')); DBMS_OUTPUT.PUT_LINE('인원 수: ' || p_emp_count || 'λͺ…'); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('ν•΄λ‹Ή λΆ€μ„œμ— 직원이 μ—†μŠ΅λ‹ˆλ‹€.'); END get_dept_salary_stats; /
SQL
볡사

예제 2: 직원 정보 일괄 μ—…λ°μ΄νŠΈ ν”„λ‘œμ‹œμ €

CREATE OR REPLACE PROCEDURE batch_update_employees ( p_dept_code IN VARCHAR2, p_salary_rate IN NUMBER DEFAULT 1.0, p_bonus_rate IN NUMBER DEFAULT 0 ) IS v_count NUMBER; BEGIN UPDATE employees SET salary = salary * p_salary_rate, bonus = bonus + p_bonus_rate WHERE dept_code = p_dept_code; v_count := SQL%ROWCOUNT; COMMIT; DBMS_OUTPUT.PUT_LINE(v_count || 'λͺ…μ˜ 직원 정보가 μ—…λ°μ΄νŠΈλ˜μ—ˆμŠ΅λ‹ˆλ‹€.'); EXCEPTION WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('였λ₯˜ λ°œμƒ: ' || SQLERRM); RAISE; END batch_update_employees; /
SQL
볡사
ν”„λ‘œμ‹œμ € ν™œμš© 팁
β€’
λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ€ ν”„λ‘œμ‹œμ €λ‘œ μΊ‘μŠν™”ν•˜μ—¬ μž¬μ‚¬μš©μ„±μ„ λ†’μ΄μ„Έμš”
β€’
νŠΈλžœμž­μ…˜ μ²˜λ¦¬κ°€ ν•„μš”ν•œ μž‘μ—…μ€ ν”„λ‘œμ‹œμ €μ—μ„œ COMMIT/ROLLBACK을 λͺ…μ‹œν•˜μ„Έμš”
β€’
μ˜ˆμ™Έ 처리λ₯Ό λ°˜λ“œμ‹œ ν¬ν•¨ν•˜μ—¬ μ•ˆμ •μ„±μ„ ν™•λ³΄ν•˜μ„Έμš”
β€’
OUT νŒŒλΌλ―Έν„°λ₯Ό ν™œμš©ν•˜μ—¬ μ—¬λŸ¬ 값을 λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€

μ£Όμš” 차이점 정리

ν•¨μˆ˜ (Function)

β€’
SELECT λ¬Έμ—μ„œ μ‚¬μš© κ°€λŠ₯
β€’
단일 κ°’ λ°˜ν™˜ ν•„μˆ˜
β€’
계산, λ³€ν™˜ μž‘μ—…μ— 적합
β€’
DML μ‚¬μš© μ œν•œμ 
β€’
νŠΈλžœμž­μ…˜ μ œμ–΄ λΆˆκ°€

ν”„λ‘œμ‹œμ € (Procedure)

β€’
λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 처리
β€’
μ—¬λŸ¬ κ°’ λ°˜ν™˜ κ°€λŠ₯ (OUT)
β€’
DML 자유둭게 μ‚¬μš©
β€’
νŠΈλžœμž­μ…˜ μ œμ–΄ κ°€λŠ₯
β€’
SELECT λ¬Έμ—μ„œ 직접 호좜 λΆˆκ°€