PL SQL - ynjch97/YNJCH_WIKI GitHub Wiki

1. PL/SQL

  • Procedural Language extension to SQL
  • SQL์„ ํ™•์žฅํ•œ ์ ˆ์ฐจ์  ์–ธ์–ด(Procedural Language)

1-1. PL/SQL ํŠน์ง•

  • ์ข…๋ฅ˜ : Procedure, Function, Trigger
  • ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์‚ฌ์šฉ๋˜๋Š” Oracle์˜ ํ‘œ์ค€ ๋ฐ์ดํ„ฐ ์—‘์„ธ์Šค ์–ธ์–ด๋กœ, ํ”„๋กœ์‹œ์ € ์ƒ์„ฑ์ž๋ฅผ SQL๊ณผ ์™„๋ฒฝํ•˜๊ฒŒ ํ†ตํ•ฉ
  • ์œ ์ € ํ”„๋กœ์„ธ์Šค๊ฐ€ PL/SQL ๋ธ”๋ก์„ ๋ณด๋‚ด๋ฉด, ์„œ๋ฒ„ ํ”„๋กœ์„ธ์„œ๋Š” PL/SQL Engine์—์„œ ํ•ด๋‹น ๋ธ”๋ก์„ ๋ฐ›๊ณ  SQL๊ณผ Procedural๋ฅผ ๋‚˜๋ˆ ์„œ SQL์€ SQL Statement Executer๋กœ ๋ณด๋ƒ„
  • ์˜ค๋ผํด์—์„œ ์ง€์›ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ํŠน์„ฑ์„ ์ˆ˜์šฉ, SQL์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ์ ˆ์ฐจ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด SQL์˜ ๋‹จ์ ์„ ๋ณด์™„

1-2. PL/SQL ์žฅ์ 

  • ํ”„๋กœ์‹œ์ € ์ƒ์„ฑ์ž์™€ SQL์˜ ํ†ตํ•ฉ
  • ์ž˜ ๋งŒ๋“ค์–ด์ง„ PL/SQL ๋ช…๋ น๋ฌธ์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ
  • ๋ชจ๋“ˆ์‹ ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ ๊ฐ€๋Šฅ : ๋…ผ๋ฆฌ์ ์ธ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ช…๋ น์–ด๋“ค์„ ํ•˜๋‚˜์˜ ๋ธ”๋ก์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ
  • ์ด์‹์„ฑ์ด ์ข‹์Œ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์•„๋ž˜์˜ SQL ๋‹จ์  ํ•ด๊ฒฐ ๊ฐ€๋Šฅ
    • ๋ณ€์ˆ˜๊ฐ€ ์—†์Œ
    • ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ๋ช…๋ น๋ฌธ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋–„๋ฌธ์— ํŠธ๋ž˜ํ”ฝ์ด ์ƒ๋Œ€์ ์œผ๋กœ ์ฆ๊ฐ€
    • ์ œ์–ด๋ฌธ ์‚ฌ์šฉ ๋ถˆ๊ฐ€ (IF, LOOP)
    • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ์—†์Œ
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ์‚ฐํ•ด์•ผ ํ•  ๋•Œ, WAS๋“ฑ์˜ ์„œ๋ฒ„๋กœ ์ „์†กํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ๋„คํŠธ์›Œํฌ์— ๋ถ€ํ•˜๊ฐ€ ๋งŽ์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Œ > ํ”„๋กœ์‹œ์ ธ๋‚˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ์‚ฐํ•˜๊ณ  ๊ฐ€๊ณตํ•œ ํ›„, ์ตœ์ข… ๊ฒฐ๊ณผ๋งŒ ์„œ๋ฒ„์— ์ „์†กํ•˜๋ฉด ๋ถ€๋‹ด์„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ
  • ๋กœ์ง ์ˆ˜์ •์„ ์œ„ํ•ด ์„œ๋ฒ„๋ฅผ ์…ง๋‹ค์šด ์‹œํ‚ค์ง€ ์•Š์•„๋„ ๋จ(์„œ๋ฒ„์—์„œ๋Š” ๋‹จ์ˆœํžˆ DB์— ํ”„๋กœ์‹œ์ €๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ๋จ)
  • ์ฟผ๋ฆฌ๋ฌธ์„ ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ SQL injection์˜ ์œ„ํ—˜์„ฑ์ด ์ค„์–ด๋“ฆ
  • ๋ธ”๋ก ๋‹จ์œ„๋กœ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

1-3. PL/SQL ๋‹จ์ 

  • ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“ฆ
  • ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ, DB์— ๋ถ€ํ•˜๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Œ
  • Git ๊ฐ™์€ ํ˜•์ƒ ๊ด€๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ

2. PL/SQL ๋ฌธ๋ฒ•

  • ๋ธ”๋ก ๋‹จ์œ„์˜ ์‹คํ–‰์„ ์ œ๊ณต
    • BEGIN๊ณผ END;๋ฅผ ์‚ฌ์šฉ
    • ๋งˆ์ง€๋ง‰ ๋ผ์ธ์— /๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํ•ด๋‹น ๋ธ”๋ก์ด ์‹คํ–‰๋˜๋„๋ก ํ•จ
  • ๋ณ€์ˆ˜, ์ƒ์ˆ˜ ๋“ฑ์„ ์„ ์–ธํ•˜์—ฌ SQL๊ณผ ์ ˆ์ฐจํ˜• ์–ธ์–ด์—์„œ ์‚ฌ์šฉ
    • ๋ณ€์ˆ˜ ์„ ์–ธ์€ DECLARE ์ ˆ์—์„œ๋งŒ ๊ฐ€๋Šฅ
    • BEGIN ์„น์…˜์—์„œ ์ƒˆ ๊ฐ’์ด ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Œ
  • IF๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์žฅ๋“ค์„ ๋ถ„๊ธฐ, LOOP๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ จ์˜ ๋ฌธ์žฅ์„ ๋ฐ˜๋ณต ๊ฐ€๋Šฅ
  • ์ปค์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ํ–‰ ๊ฒ€์ƒ‰ ๋ฐ ์ฒ˜๋ฆฌ
  • PL/SQL์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ SQL : Query, DML, TCL
    • DDL(CREATE, DROP, ALTER, TRUNCATE โ€ฆ), DCL(GRANT, REVOKE) ๋ช…๋ น์–ด๋Š” ๋™์  SQL์„ ์ด์šฉํ•  ๋•Œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • PL/SQL์˜ SELECT๋ฌธ์€ ํ•ด๋‹น SELECT์˜ ๊ฒฐ๊ณผ๋ฅผ PL/SQL Engine์œผ๋กœ ๋ณด๋‚ธ๋‹ค.
    • ์ด๋ฅผ ์บ์น˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ DECLARE ํ•ด์•ผ ํ•จ
    • INTO ์ ˆ์„ ์„ ์–ธํ•˜์—ฌ ๋„ฃ์„ ๋ณ€์ˆ˜๋ฅผ ๊ผญ ํ‘œํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•จ
    • SELECT ๋ฌธ์žฅ์€ ๋ฐ˜๋“œ์‹œ ํ•œ ๊ฐœ์˜ ํ–‰์ด ๊ฒ€์ƒ‰๋˜์–ด์•ผ ํ•จ
    • INTO์ ˆ์ด ๋ˆ„๋ฝ๋˜๊ฑฐ๋‚˜, ๊ฒ€์ƒ‰๋˜๋Š” ํ–‰์ด ์—†์œผ๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ
  • ํ•œ ๋ฌธ์žฅ์ด ์ข…๋ฃŒํ•  ๋•Œ๋งˆ๋‹ค ์„ธ๋ฏธ์ฝœ๋ก (;)์„ ์‚ฌ์šฉ, ํ•œ ๋ฌธ์žฅ์ด ๋๋‚ฌ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹œ
  • ๋‹จ์ผํ–‰ ์ฃผ์„ -- / ์—ฌ๋Ÿฌ ํ–‰ ์ฃผ์„ /* */

2-1. PL/SQL ๊ตฌ์กฐ

2-1-1. DECLARE(์„ ์–ธ๋ถ€)

  • PL/SQL์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๋ณ€์ˆ˜๋‚˜ ์ƒ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ถ€๋ถ„
  • ๋ณ€์ˆ˜/์ƒ์ˆ˜/์ปค์„œ ๋“ฑ์„ ์„ ์–ธ

2-1-2. BEGIN(์‹คํ–‰๋ถ€)

  • ์ ˆ์ฐจ์  ํ˜•์‹์œผ๋กœ SQL๋ฌธ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ ˆ์ฐจ์  ์–ธ์–ด์˜ ์š”์†Œ์ธ ์ œ์–ด๋ฌธ, ๋ฐ˜๋ณต๋ฌธ, ํ•จ์ˆ˜ ์ •์˜ ๋“ฑ ๋กœ์ง์„ ๊ธฐ์ˆ 
  • ํ•„์ˆ˜์ ์œผ๋กœ ์กด์žฌํ•ด์•ผ ํ•จ

2-1-3. EXCEPTION(์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ถ€)

  • PL/SQL๋ฌธ์ด ์‹คํ–‰๋˜๋Š” ์ค‘์— ๋ฐœ์ƒ๋˜๋Š” ์—๋Ÿฌ(์˜ˆ์™ธ ์‚ฌํ•ญ)๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ์žฅ์„ ๊ธฐ์ˆ 

2-1-4. END(์‹คํ–‰๋ฌธ ์ข…๋ฃŒ)

  • END ๋’ค์— ์„ธ๋ฏธ์ฝœ๋ก (;)์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ธ”๋ก์ด ๋๋‚ฌ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹œ
  • ํ•„์ˆ˜์ ์œผ๋กœ ์กด์žฌํ•ด์•ผ ํ•จ

2-2. PL/SQL Block์˜ ์ข…๋ฅ˜

  • ์ต๋ช… ๋ธ”๋ก : ์ด๋ฆ„์ด ์—†๋Š” PL/SQL Block
  • ์ด๋ฆ„ ์žˆ๋Š” ๋ธ”๋ก : DB์˜ ๊ฐ์ฒด๋กœ ์ €์žฅ๋˜๋Š” ๋ธ”๋ก
    • ํ”„๋กœ์‹œ์ € : ๋ฆฌํ„ด ๊ฐ’์„ ํ•˜๋‚˜ ์ด์ƒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ
    • ํ•จ์ˆ˜ : ๋ฆฌํ„ด ๊ฐ’์„ ๋ฐ˜๋“œ์‹œ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ
    • ํŒจํ‚ค์ง€ : ํ•˜๋‚˜ ์ด์ƒ์˜ ํ”„๋กœ์‹œ์ €, ํ•จ์ˆ˜, ๋ณ€์ˆ˜, ์˜ˆ์™ธ ๋“ฑ์˜ ๋ฌถ์Œ
    • ํŠธ๋ฆฌ๊ฑฐ : ์ง€์ •๋œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๋Š” PL/SQL ๋ธ”๋ก

3. ์‹ค์Šต ์ค€๋น„

3-1. PL/SQL ๊ฒฐ๊ณผ ์ถœ๋ ฅ

  • PUT_LINE ํ”„๋กœ์‹œ์ €๋ฅผ ์ด์šฉ
  • ํ”„๋กœ์‹œ์ €๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถœ๋ ฅ๋˜๋Š” ๋‚ด์šฉ์„ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜ SERVEROUTPUT(๋””ํดํŠธ๊ฐ’์ด OFF์ด๋ฏ€๋กœ) ON์œผ๋กœ ๋ณ€๊ฒฝ
SET serveroutput ON
BEGIN 
    dbms_output.put_line('ynjch');
END;

3-2. ํ…Œ์ŠคํŠธ์šฉ ํ…Œ์ด๋ธ” ์ค€๋น„

  • USER_INFO ํ…Œ์ด๋ธ” ์ƒ์„ฑ
CREATE TABLE USER_INFO 
(
    USER_NUM NUMBER(10) NOT NULL 
    , USER_NM VARCHAR2(20) 
    , USER_BIRTH VARCHAR2(8)
    , CONSTRAINT user_info_pk PRIMARY KEY(USER_NUM)
);
SELECT * FROM USER_INFO;
DROP TABLE USER_INFO;
  • USER_INFO ํ…Œ์ด๋ธ” ์‹œํ€€์Šค ์ƒ์„ฑ
CREATE SEQUENCE USER_NUM_SEQ START WITH 1 INCREMENT BY 1 MAXVALUE 10000000 CYCLE NOCACHE;
  • ์‹œํ€€์Šค ์กฐํšŒ ๋ฐ ์ดˆ๊ธฐํ™”
SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'USER_NUM_SEQ';
ALTER SEQUENCE USER_NUM_SEQ INCREMENT BY -1000;
SELECT USER_NUM_SEQ.NEXTVAL FROM DUAL;
ALTER SEQUENCE USER_NUM_SEQ INCREMENT BY 1;
  • USER_SCORE ํ…Œ์ด๋ธ” ์ƒ์„ฑ
CREATE TABLE USER_SCORE 
(
    USER_NUM NUMBER(10) NOT NULL 
    , USER_GRADE VARCHAR(5)
    , CONSTRAINT user_score_pk PRIMARY KEY(USER_NUM)
);
SELECT * FROM USER_SCORE;
DROP TABLE USER_SCORE;
  • USER_INFO ๋ฐ์ดํ„ฐ INSERT
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '์ฐจ์€์šฐ', '19971026');
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '๊ฐ•ํƒœ์˜ค', '19971001');
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '์„œ๊ฐ•์ค€', '19911022');
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '์†ก๊ฐ•', '20010107');
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '๋กœ์šด', '19710606');
INSERT INTO USER_INFO values(USER_NUM_SEQ.NEXTVAL, '๊น€์ˆ˜ํ˜„', '19970714');
INSERT INTO USER_SCORE values(1, 'A');
INSERT INTO USER_SCORE values(2, 'C');
INSERT INTO USER_SCORE values(3, 'A');
INSERT INTO USER_SCORE values(4, 'D');
INSERT INTO USER_SCORE values(5, 'B');
INSERT INTO USER_SCORE values(6, 'C');
  • STORE_INFO ํ…Œ์ด๋ธ” ์ƒ์„ฑ
CREATE TABLE STORE_INFO 
(
    STORE_NUM NUMBER(10) NOT NULL 
    , STORE_NM VARCHAR2(30) 
    , STORE_TEL VARCHAR2(20) 
    , STORE_ADDR VARCHAR2(30)
    , OWNER_NUM NUMBER(10)
    , CONSTRAINT store_info_pk PRIMARY KEY(STORE_NUM)
    , CONSTRAINT store_info_fk FOREIGN KEY(OWNER_NUM) REFERENCES USER_INFO (USER_NUM)
);
SELECT * FROM STORE_INFO;
DROP TABLE STORE_INFO;
  • STORE_INFO ํ…Œ์ด๋ธ” ์‹œํ€€์Šค ์ƒ์„ฑ
CREATE SEQUENCE STORE_NUM_SEQ START WITH 1 INCREMENT BY 1 MAXVALUE 10000000 CYCLE NOCACHE;
  • ์‹œํ€€์Šค ์กฐํšŒ ๋ฐ ์ดˆ๊ธฐํ™”
SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'STORE_NUM_SEQ';
ALTER SEQUENCE STORE_NUM_SEQ INCREMENT BY -1000;
SELECT STORE_NUM_SEQ.NEXTVAL FROM DUAL;
ALTER SEQUENCE STORE_NUM_SEQ INCREMENT BY 1;
  • ์‹œํ€€์Šค ์ฆ๊ฐ€ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ
CREATE FUNCTION FUNC_STORE_NUM_SEQ RETURN NUMBER IS
BEGIN
    RETURN STORE_NUM_SEQ.NEXTVAL;
END;
/
SELECT * FROM USER_SOURCE WHERE TYPE = 'FUNCTION' AND NAME = 'FUNC_STORE_NUM_SEQ';
DROP FUNCTION FUNC_STORE_NUM_SEQ;
  • STORE_INFO ๋ฐ์ดํ„ฐ INSERT
INSERT INTO STORE_INFO (STORE_NUM, STORE_NM, STORE_TEL, STORE_ADDR, OWNER_NUM)
SELECT              FUNC_STORE_NUM_SEQ, '์ฝ”์ŠคํŠธ์ฝ” ๋Œ€์ „์ ', '033-345-5751', '๋Œ€์ „์‹œ ์ค‘๊ตฌ', 1 FROM DUAL
UNION ALL SELECT    FUNC_STORE_NUM_SEQ, '๊ด‘๋ช… IKEA', '02-111-4453', '๊ฒฝ๊ธฐ๋„ ๊ด‘๋ช…์‹œ', 2 FROM DUAL
UNION ALL SELECT    FUNC_STORE_NUM_SEQ, '๊ต๋ณด๋ฌธ๊ณ  ๊ด‘ํ™”๋ฌธ์ ', '02-2341-4277', '์„œ์šธ์‹œ ์ข…๋กœ๊ตฌ', 3 FROM DUAL
UNION ALL SELECT    FUNC_STORE_NUM_SEQ, '์‹ ์„ธ๊ณ„ ์˜๋“ฑํฌ์ ', '02-3245-8775', '์„œ์šธ์‹œ ์˜๋“ฑํฌ๊ตฌ', 5 FROM DUAL
UNION ALL SELECT    FUNC_STORE_NUM_SEQ, '63๋นŒ๋”ฉ ์•„์ฟ ์•„๋ฆฌ์›€', '02-2341-4277', '์„œ์šธ์‹œ ์˜๋“ฑํฌ๊ตฌ', 5 FROM DUAL;

COMMIT;

4. ๋ณ€์ˆ˜

  • ์„ ์–ธ๋ถ€(DECLARE) ๋ณ€์ˆ˜๋ช…, ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ๊ธฐ์ˆ 
    • identifier : ๋ณ€์ˆ˜๋ช…(์‹๋ณ„์ž)
    • CONSTANT : ์ƒ์ˆ˜๋กœ ์ง€์ • (์ดˆ๊ธฐ์น˜๋ฅผ ๋ฐ˜๋“œ์‹œ ํ• ๋‹นํ•ด์•ผ ํ•จ)
    • datatype : ์ž๋ฃŒํ˜•์„ ๊ธฐ์ˆ 
    • NOT NULL : ๊ฐ’์„ ๋ฐ˜๋“œ์‹œ ํฌํ•จ
    • expression : Literal, ๋‹ค๋ฅธ ๋ณ€์ˆ˜, ์—ฐ์‚ฐ์ž๋‚˜ ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•˜๋Š” ํ‘œํ˜„์‹
identifier [CONSTANT] datatype [NOT NULL] [:=|DEFAULT expression];

4-1. ๋ณ€์ˆ˜ ์„ ์–ธ

  • ๋‹จ์ผ ๋ณ€์ˆ˜ ์„ ์–ธ
DECLARE NAME VARCHAR2(10);
DECLARE NAME VARCHAR2(10) := 'ynjch';
DECLARE NAME VARCHAR2(10) DEFAULT 'ynjch';
  • ์—ฌ๋Ÿฌ ๊ฐœ ์„ ์–ธ ์‹œ
DECLARE 
	NAME    VARCHAR2(20);
	AGE     NUMBER(2); 
	GENDER  VARCHAR(5)   DEFAULT '์—ฌ';

4-2. Type์œผ๋กœ ๋ณ€์ˆ˜ ์„ ์–ธ

4-2-1. %ROWTYPE

  • ํ•ด๋‹น ํ…Œ์ด๋ธ”์ด๋‚˜ ๋ทฐ์˜ ์ปฌ๋Ÿผ ์†์„ฑ์„ ๊ทธ๋Œ€๋กœ ๋“ค๊ณ  ์˜ค๋Š” ํ˜•ํƒœ
    • ๋ณ€์ˆ˜๋ช… ํ…Œ์ด๋ธ”๋ช…%ROWTYPE
DECLARE
    userNum NUMBER(5) := 1;
    rowData USER_INFO%ROWTYPE;
BEGIN
    SELECT * INTO rowData
    FROM USER_INFO
    WHERE USER_NUM = userNum;
    dbms_output.put_line(rowData.USER_NUM||'. '||rowData.USER_NM);
END;

4-2-2. %TYPE

  • ํ•ด๋‹น ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ ์†์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ๊ทธ๋Œ€๋กœ ๋“ค๊ณ  ์˜ค๋Š” ํ˜•ํƒœ
    • ๋ณ€์ˆ˜๋ช… ํ…Œ์ด๋ธ”๋ช….์ปฌ๋Ÿผ๋ช…%TYPE
DECLARE
    userNum NUMBER(5) := 1;
    userNm USER_INFO.USER_NM%TYPE;
    userBirth USER_INFO.USER_BIRTH%TYPE;
BEGIN
    SELECT
        USER_NM, USER_BIRTH INTO userNm, userBirth
    FROM USER_INFO
    WHERE USER_NUM = userNum;
    dbms_output.put_line(userNm||'('||userBirth||')');
END;
  • SELECT ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ๊ฐ’ ๋Œ€์ž…
    • INTO ์ ˆ์— ์กฐํšŒ ๊ฒฐ๊ณผ ๊ฐ’์„ ์ €์žฅํ•  ๋ณ€์ˆ˜๋ฅผ ๊ธฐ์ˆ 
    • SELECT ๋ฌธ์€ INTO ์ ˆ์— ์˜ํ•ด ํ•˜๋‚˜์˜ ํ–‰๋งŒ์„ ์ €์žฅ ๊ฐ€๋Šฅ
    • SELECT ์ดํ›„ ์ž‘์„ฑํ•œ ์ปฌ๋Ÿผ์€ INTO ์ ˆ์— ์žˆ๋Š” ๋ณ€์ˆ˜์™€ 1:1๋กœ ๋Œ€์‘ํ•ด์•ผ ํ•จ > ๊ฐœ์ˆ˜์™€ ๋ฐ์ดํ„ฐ ํƒ€์ž…, ๊ธธ์ด๋ฅผ ์ผ์น˜์‹œ์ผœ์•ผ ํ•จ

5. ๋ฐ˜๋ณต๋ฌธ

  • FOR LOOP๋ฌธ, LOOP๋ฌธ์œผ๋กœ ๋‚˜๋‰จ

5-1. FOR LOOP๋ฌธ

  • index๋Š” ์ž๋™ ์„ ์–ธ๋˜๋Š” binary_integerํ˜• ๋ณ€์ˆ˜์ด๋ฉฐ 1์”ฉ ์ฆ๊ฐ€
  • REVERSE ์˜ต์…˜์ด ์‚ฌ์šฉ ๋  ๊ฒฝ์šฐ index๋Š” upper_bound์—์„œ lower_bound๋กœ 1์”ฉ ๊ฐ์†Œ
  • IN ๋‹ค์Œ์—๋Š” coursor๋‚˜ SELECT ๋ฌธ์ด ์˜ฌ ์ˆ˜ ์žˆ์Œ
FOR index in [REVERSE] ์‹œ์ž‘๊ฐ’ .. END๊ฐ’ LOOP
    STATEMENT 1
    STATEMENT 2
    ...
END LOOP;

5-1-1. ์˜ˆ์ œ

  • ์ง์ˆ˜, ํ™€์ˆ˜ ํŒ๋ณ„
    • IF๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ
BEGIN
    FOR i IN 1..5 LOOP
        IF MOD(i,2) = 0 THEN 
            dbms_output.put_line(i||'๋Š” ์ง์ˆ˜');
        ELSE
            dbms_output.put_line(i||'๋Š” ํ™€์ˆ˜');
        END IF;
    END LOOP;
END;
  • USER_NUM 1~3 ๊นŒ์ง€์˜ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅํ•˜๊ธฐ
DECLARE
    userNum NUMBER(5) := 1;
    rowData USER_INFO%ROWTYPE;
BEGIN
    FOR i IN 1..3 LOOP
        userNum := i;
        SELECT * INTO rowData
        FROM USER_INFO
        WHERE USER_NUM = userNum;
        dbms_output.put_line(rowData.USER_NM||'('||rowData.USER_NUM||')');
    END LOOP;
END;
  • SELECT ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ๋ณ„๋„์˜ ๋ณ€์ˆ˜ ์„ ์–ธ ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ
BEGIN
    FOR userList IN (
        SELECT * FROM USER_INFO
    ) LOOP
        dbms_output.put_line(userList.USER_NM||'('||userList.USER_NUM||')');
    END LOOP;
END;
  • ๋‚˜์™€ ๋‚˜์ด ๋น„๊ตํ•˜๊ธฐ
DECLARE
    userNum NUMBER(5) := 1;
    rowData USER_INFO%ROWTYPE;
BEGIN
    SELECT * INTO rowData
    FROM USER_INFO
    WHERE USER_NUM = userNum;
        
    FOR userList IN (
        SELECT * FROM USER_INFO WHERE USER_NUM <> userNum
    ) LOOP
        IF ( SUBSTR(rowData.USER_BIRTH,1,4) = SUBSTR(userList.USER_BIRTH,1,4) ) THEN
            dbms_output.put_line(userList.USER_NM||'์€(๋Š”) '||rowData.USER_NM||'์˜ ์นœ๊ตฌ');
        ELSIF ( SUBSTR(rowData.USER_BIRTH,1,4) > SUBSTR(userList.USER_BIRTH,1,4) ) THEN
            dbms_output.put_line(userList.USER_NM||'์€(๋Š”) '||rowData.USER_NM||'๋ณด๋‹ค ๋‚˜์ด๊ฐ€ ๋งŽ๋‹ค');
        ELSE 
            dbms_output.put_line(userList.USER_NM||'์€(๋Š”) '||rowData.USER_NM||'๋ณด๋‹ค ๋‚˜์ด๊ฐ€ ์ ๋‹ค');
        END IF;
    END LOOP;
END;

5-1-2. ์˜ˆ์ œ

  • ํ…Œ์ด๋ธ” JOINํ•˜์—ฌ ์œ ์ €๋“ค์˜ ์ ์ˆ˜ ์กฐํšŒํ•˜๊ธฐ 1
    • USER_INFO, USER_SCORE ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์„ ๋‹ด์€ ํŠธ๋žœ์žญ์…˜ GTT ์ƒ์„ฑ(TX_USER_INFO_SCORE)
    • WITH๋ฌธ, FOR LOOP๋ฌธ ์‚ฌ์šฉ
CREATE GLOBAL TEMPORARY TABLE TX_USER_INFO_SCORE (
    USER_NUM NUMBER(10) NOT NULL 
    , USER_NM VARCHAR2(20) 
    , USER_BIRTH VARCHAR2(8)
    , USER_GRADE VARCHAR(5)
)
ON COMMIT DELETE ROWS;

DECLARE
    userCnt NUMBER;
    rowData TX_USER_INFO_SCORE%ROWTYPE;
BEGIN 
    -- 1. userCnt ๊ตฌํ•˜๊ธฐ 
    SELECT COUNT(1) INTO userCnt FROM USER_INFO;
    dbms_output.put_line('userCnt : '||userCnt);
    
    -- 2. for loop
    FOR i IN 1..userCnt LOOP
        WITH TEMP_USER_INFO_SCORE AS -- WITH ๋ฌธ
        (
            SELECT I.USER_NUM, I.USER_NM, I.USER_BIRTH, S.USER_GRADE
            FROM USER_INFO I
            LEFT JOIN USER_SCORE S
            ON I.USER_NUM = S.USER_NUM
        )
        SELECT * INTO rowData FROM TEMP_USER_INFO_SCORE WHERE USER_NUM = i;
        dbms_output.put_line(rowData.USER_NM ||'('|| rowData.USER_NUM ||')''s score : ' || rowData.USER_GRADE);
    END LOOP;
END;
  • ํ…Œ์ด๋ธ” JOINํ•˜์—ฌ ์œ ์ €๋“ค์˜ ์ ์ˆ˜ ์กฐํšŒํ•˜๊ธฐ 2
    • FOR [๋ณ€์ˆ˜๋ช…] IN [์ฟผ๋ฆฌ] LOOP ์‚ฌ์šฉ
    • WITH๋ฌธ, FOR LOOP๋ฌธ ์‚ฌ์šฉ
DECLARE
BEGIN     
    FOR userList IN (
        WITH TEMP_USER_INFO_SCORE AS -- WITH ๋ฌธ
        (
            SELECT I.USER_NUM, I.USER_NM, I.USER_BIRTH, S.USER_GRADE
            FROM USER_INFO I
            LEFT JOIN USER_SCORE S
            ON I.USER_NUM = S.USER_NUM
        )
        SELECT * FROM TEMP_USER_INFO_SCORE ORDER BY USER_NUM
    ) LOOP
        dbms_output.put_line(userList.USER_NM ||'('|| userList.USER_NUM ||')''s score : ' || userList.USER_GRADE);
    END LOOP;
END;

5-2. LOOP๋ฌธ

  • EXIT : ๋ฌด์กฐ๊ฑด LOOP ๋ฌธ์„ ๋น ์ ธ๋‚˜๊ฐ
  • EXIT WHEN : WHEN ์ ˆ์—์„œ LOOP๋ฅผ ๋น ์ ธ๋‚˜๊ฐ€๋Š” ์กฐ๊ฑด์„ ์ œ์–ด
LOOP 
    STATEMENT 1
        ๋‹ค๋ฅธ LOOP๋ฅผ ํฌํ•จํ•˜์—ฌ ์ค‘์ฒฉ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    EXIT [WHEN CONDITION]
END LOOP;

5-2-1. ์˜ˆ์ œ

  • 1์—์„œ 5๊นŒ์ง€ ์ˆซ์ž ์ถœ๋ ฅํ•˜๊ธฐ
DECLARE
    startNum NUMBER := 1;
    endNum NUMBER := 5;
    loopCnt NUMBER := 0;
BEGIN
    LOOP
        dbms_output.put_line('ํ˜„์žฌ ์ˆซ์ž : '||startNum);
        loopCnt := loopCnt + 1;
        startNum := startNum + 1;
        EXIT WHEN loopCnt >= endNum;
    END LOOP;
    dbms_output.put_line('๋ฐ˜๋ณต ํšŸ์ˆ˜ : '||loopCnt);
END;

5-2-2. WHILE LOOP๋ฌธ

  • 5-2-1. ์˜ ์˜ˆ์ œ๋ฅผ WHILE LOOP๋ฌธ์œผ๋กœ ํ‘œํ˜„
DECLARE
    startNum NUMBER := 1;
    endNum NUMBER := 5;
    loopCnt NUMBER := 0;
BEGIN
    WHILE loopCnt < endNum LOOP
        dbms_output.put_line('ํ˜„์žฌ ์ˆซ์ž : '||startNum);
        loopCnt := loopCnt + 1;
        startNum := startNum + 1;
    END LOOP;
    dbms_output.put_line('๋ฐ˜๋ณต ํšŸ์ˆ˜ : '||loopCnt);
END;

6. ์ œ์–ด๋ฌธ

  • ์ผ๋ฐ˜์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์‚ฌ์šฉ๋˜๋Š” IF๋ฌธ, CASE๋ฌธ ๋“ฑ์˜ ์ œ์–ด๋ฌธ(์กฐ๊ฑด์ ˆ) ์‚ฌ์šฉ ๊ฐ€๋Šฅ

6-1. IF๋ฌธ

  • ELSE IF๋ฅผ ELSIF๋กœ ์“ฐ๋Š” ๊ฒƒ์— ์ฃผ์˜
IF ์กฐ๊ฑด1 THEN
    ์ฒ˜๋ฆฌ๋ฌธ1
ELSIF ์กฐ๊ฑด2 THEN
    ์ฒ˜๋ฆฌ๋ฌธ2
ELSE
    ์ฒ˜๋ฆฌ๋ฌธ
END IF;

6-1-1. ์˜ˆ์ œ

DECLARE
    userNum NUMBER := 1;
    userBirthYear VARCHAR(4);
    rowData USER_INFO%ROWTYPE;
BEGIN
    SELECT * INTO rowData
    FROM USER_INFO
    WHERE USER_NUM = userNum;
    userBirthYear := SUBSTR(rowData.USER_BIRTH, 1, 4);
    
    IF (2022 - userBirthYear + 1) > 49 THEN
        DBMS_OUTPUT.PUT_LINE(rowData.USER_NM||'๋‹˜์€ 50์„ธ ์ด์ƒ์ž…๋‹ˆ๋‹ค.');
    ELSIF (2022 - userBirthYear + 1) > 29 THEN
        DBMS_OUTPUT.PUT_LINE(rowData.USER_NM||'๋‹˜์€ 30์„ธ ์ด์ƒ์ž…๋‹ˆ๋‹ค.');
    ELSIF (2022 - userBirthYear + 1) > 19 THEN
        DBMS_OUTPUT.PUT_LINE(rowData.USER_NM||'๋‹˜์€ 20์„ธ ์ด์ƒ์ž…๋‹ˆ๋‹ค.');
    ELSE
        DBMS_OUTPUT.PUT_LINE(rowData.USER_NM||'๋‹˜์€ 20์„ธ ๋ฏธ๋งŒ์ž…๋‹ˆ๋‹ค.');
    END IF;
END;

6-2. CASE๋ฌธ

  • ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๊ฐ’์„ ๋Œ€์ž…ํ•˜๊ฑฐ๋‚˜, PL/SQL ๋ช…๋ น๋ฌธ ์‹คํ–‰ ์‹œ ์‚ฌ์šฉ

6-2-1. ์˜ˆ์ œ

  • ์„ฑ์  ํ™•์ธ
DECLARE
    userNum NUMBER := 1;
    userGrade USER_SCORE.USER_GRADE%TYPE;
    resultStr VARCHAR(30);
BEGIN 
    SELECT USER_GRADE INTO userGrade
    FROM USER_SCORE 
    WHERE USER_NUM = userNum;
    
    resultStr := 
    CASE userGrade
        WHEN 'A' THEN 'Perfect'
        WHEN 'B' THEN 'Very Good'
        WHEN 'C' THEN 'Good'
        ELSE 'Hmm...'
    END;
    DBMS_OUTPUT.PUT_LINE(userGrade||' is '||resultStr);
END;

7. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ์‹œ์Šคํ…œ ์˜ˆ์™ธ : Oracle์—์„œ ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ์ •์˜ํ•ด๋†“์€ ์˜ˆ์™ธ
  • ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ : ์˜ˆ์ƒ๋˜๋Š” ํŠน์ • ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ •์˜ํ•œ ์˜ˆ์™ธ
  • ์ฒ˜๋ฆฌํ•  ์˜ˆ์™ธ๋“ค์„ ์ฐจ๋ก€๋กœ ์„ ์–ธํ•œ ๋’ค, ๋งˆ์ง€๋ง‰์— OTHERS๋ฅผ ์„ ์–ธํ•˜์—ฌ ๋‚˜๋จธ์ง€ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•จ
EXCEPTION WHEN [์˜ˆ์™ธ๋ช…1] THEN [์˜ˆ์™ธ์ฒ˜๋ฆฌ ๊ตฌ๋ฌธ1]
WHEN [์˜ˆ์™ธ๋ช…2] THEN [์˜ˆ์™ธ์ฒ˜๋ฆฌ ๊ตฌ๋ฌธ2];

7-1. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ํ”„๋กœ์‹œ์ € ์‹คํ–‰ ํ›„ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ๋กœ์ง์€ ์ •์ƒ ์ž‘๋™๋˜๋„๋ก ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ตฌ๋ฌธ ์ž‘์„ฑ
CREATE OR REPLACE PROCEDURE PROC_TEST
IS
    v_num NUMBER := 0;
BEGIN
    v_num := 10/0;
    EXCEPTION WHEN OTHERS THEN 
        dbms_output.put_line('์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค!');
        dbms_output.put_line('์—๋Ÿฌ์ฝ”๋“œ : ' || SQLCODE);
        dbms_output.put_line('์—๋Ÿฌ๋ฉ”์‹œ์ง€ : ' || SQLERRM);
        dbms_output.put_line('๋งค๊ฐœ๋ณ€์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ๋ฉ”์‹œ์ง€ : ' || SQLERRM(SQLCODE));
END;
/
EXEC PROC_TEST();
/* ๊ฒฐ๊ณผ
์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค!
์—๋Ÿฌ์ฝ”๋“œ : -1476
์—๋Ÿฌ๋ฉ”์‹œ์ง€ : ORA-01476: ์ œ์ˆ˜๊ฐ€ 0 ์ž…๋‹ˆ๋‹ค
๋งค๊ฐœ๋ณ€์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ๋ฉ”์‹œ์ง€ : ORA-01476: ์ œ์ˆ˜๊ฐ€ 0 ์ž…๋‹ˆ๋‹ค */

7-2. ์‹œ์Šคํ…œ ์˜ˆ์™ธ

  • Oracle์—์„œ ์ง€์›ํ•˜๋Š” ๋Œ€ํ‘œ์  ์‹œ์Šคํ…œ ์˜ˆ์™ธ ๋ชฉ๋ก
์˜ˆ์™ธ๋ช… ์˜ˆ์™ธ ์ฝ”๋“œ ์„ค๋ช…
PROGRAM_ERROR ORA-06501 PL/SQL ์ฝ”๋“œ์ƒ์—์„œ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋‚ฌ์„ ๊ฒฝ์šฐ
STORAGE_ERROR ORA-06500 ํ”„๋กœ๊ทธ๋žจ ์ˆ˜ํ–‰ ์‹œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•  ๊ฒฝ์šฐ
TIMEOUT_ON_RESOURCE ORA-00051 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ ์‹œ
NO_DATA_FOUND ORA-01403 SELECT INTO ์‹œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ ๊ฑด๋„ ์—†์„ ๊ฒฝ์šฐ
TOO_MANY_ROWS ORA-01422 SELECT INTO ์ ˆ ์‚ฌ์šฉํ•  ๋•Œ ๊ฒฐ๊ณผ๊ฐ€ ํ•œ ๋กœ์šฐ ์ด์ƒ์ผ ๋•Œ
VALUE_ERROR ORA-06502 ์ˆ˜์น˜ ๋˜๋Š” ๊ฐ’ ์˜ค๋ฅ˜
ZERO_DIVIDE ORA-01476 0์œผ๋กœ ๋‚˜๋ˆŒ ๋•Œ
INVALID_NUMBER ORA-01722 ๋ฌธ์ž๋ฅผ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‹คํŒจํ•  ๊ฒฝ์šฐ
DUP_VAL_ON_INDEX ORA-00001 ์œ ์ผ ์ธ๋ฑ์Šค๊ฐ€ ์žˆ๋Š” ์ปฌ๋Ÿผ์— ์ค‘๋ณต๊ฐ’์œผ๋กœ INSERT, UPDATE ์ˆ˜ํ–‰
CASE_NOT_FOUND ORA-06592 CASE๋ฌธ ์‚ฌ์šฉ ์‹œ ๊ตฌ๋ฌธ ์˜ค๋ฅ˜
ACCESS_INTO_NULL ORA-06530 LOB๊ณผ ๊ฐ™์€ ๊ฐ์ฒด ์ดˆ๊ธฐํ™” ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ์‚ฌ์šฉ
CURSOR_ALREADY_OPEN ORA-06511 ์ปค์„œ๊ฐ€ ์ด๋ฏธ OPEN ๋œ ์ƒํƒœ์ธ๋ฐ OPEN ํ•˜๋ ค๊ณ  ์‹œ๋„
INVALID_CURSOR ORA-01001 ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ปค์„œ๋ฅผ ์ฐธ์กฐ
NOT_LOGGED_ON ORA-01012 ๋กœ๊ทธ์˜จ๋˜์ง€ ์•Š์•˜๋Š”๋ฐ DB๋ฅผ ์ฐธ์กฐํ•  ๋•Œ
LOGIN_DENIED ORA-01017 ์ž˜๋ชป๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„์ด๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ๋กœ๊ทธ์ธ์„ ์‹œ๋„

7-3. ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ

  • ์ž…๋ ฅ ๋ฐ›์€ ๊ฐ’์ด ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ”„๋กœ์‹œ์ € ๊ตฌ์„ฑ
  • RAISE : ์ง์ ‘ ์ •์˜ํ•œ ์˜ˆ์™ธ, ์‹œ์Šคํ…œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ
    • ex_not_exist_num EXCEPTION; : ์„ ์–ธ๋ถ€์— ์ž‘์„ฑํ•˜์—ฌ ์˜ˆ์™ธ๋ฅผ ์ •์˜
    • RAISE NO_DATA_FOUND; : ์‹œ์Šคํ…œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋„๋ก ํ•จ
CREATE OR REPLACE PROCEDURE PROC_CHK_USER_NUM (p_user_num USER_INFO.USER_NUM%TYPE)
IS
    v_cnt NUMBER := 0;
    ex_not_exist_num EXCEPTION;
BEGIN
    SELECT COUNT(1)
    INTO v_cnt
    FROM USER_INFO 
    WHERE USER_NUM = p_user_num;
    
    -- ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ฅธ ๊ฒฐ๊ณผ๊ฐ’ ์กฐ๊ฑด ์ฒ˜๋ฆฌ
    IF p_user_num = 1 THEN
        RAISE NO_DATA_FOUND;
    ELSIF v_cnt > 0 THEN 
        dbms_output.put_line('๋“ฑ๋ก๋œ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค.');
    ELSE 
        RAISE ex_not_exist_num;
    END IF;
    
    -- ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
        dbms_output.put_line('NO_DATA_FOUND!!');
    WHEN ex_not_exist_num THEN
        dbms_output.put_line('๋“ฑ๋ก๋œ ์‚ฌ์šฉ์ž๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.');
    WHEN OTHERS THEN
        dbms_output.put_line(SQLERRM);
END;
/

-- ๊ฒฐ๊ณผ 
EXEC PROC_CHK_USER_NUM(1); /* NO_DATA_FOUND!! */
EXEC PROC_CHK_USER_NUM(2); /* ๋“ฑ๋ก๋œ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค. */
EXEC PROC_CHK_USER_NUM(111); /* ๋“ฑ๋ก๋œ ์‚ฌ์šฉ์ž๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. */
EXEC PROC_CHK_USER_NUM('YNJCH'); 
/* ORA-06502: PL/SQL: ์ˆ˜์น˜ ๋˜๋Š” ๊ฐ’ ์˜ค๋ฅ˜: ๋ฌธ์ž๋ฅผ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค */

7-4. ์˜ˆ์™ธ ๋‚ด์šฉ ํ™•์ธ

  • Oracle์—์„œ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜๋Š” ๋นŒํŠธ์ธ(built-in) ํ•จ์ˆ˜ ์ด์šฉ
    • SQLCODE : ์‹คํ–‰๋ถ€์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ์— ํ•ด๋‹นํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜
    • SQLERRM : ์˜ˆ์™ธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๋ฉ”์‹œ์ง€ ๋ฐ˜ํ™˜
  • ์ƒ์„ธ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด dbms_utility ์ด์šฉ
    • dbms_utility.format_call_stack
    • dbms_utility.format_error_stack
    • dbms_utility.format_error_backtrace

7-4-1. ํšจ์œจ์ ์ธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

  • ์‹œ์Šคํ…œ ์˜ˆ์™ธ์ธ ๊ฒฝ์šฐ OTHERS ์‚ฌ์šฉ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฃจํ‹ด์„ ๊ณตํ†ต ๋ชจ๋“ˆํ™”ํ•˜์—ฌ, ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๋„๋ก ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌ
  • ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ๋Š” ๋ณ„๋„ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌ