🎯 학습 목표
- SELECT … INTO로 쿼리 결과를 PL/SQL 변수에 담는다.
- NO_DATA_FOUND, TOO_MANY_ROWS 예외가 발생하는 상황을 안다.
- INSERT/UPDATE/DELETE를 PL/SQL 안에서 실행하고 COMMIT/ROLLBACK을 제어한다.
- 암시적 커서 속성(SQL%ROWCOUNT, SQL%FOUND)으로 DML 결과를 확인한다.
📖 SELECT INTO — 한 행을 변수에 담기
PL/SQL에서 SELECT 결과를 변수에 담으려면 반드시 INTO를 씁니다. 결과가 정확히 한 행이어야 합니다.
DECLARE
v_name emp.ename%TYPE;
v_sal emp.sal%TYPE;
v_dept emp.deptno%TYPE;
BEGIN
SELECT ename, sal, deptno
INTO v_name, v_sal, v_dept
FROM emp
WHERE empno = 7369;
DBMS_OUTPUT.PUT_LINE(v_name || ' / 급여: ' || v_sal || ' / 부서: ' || v_dept);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('해당 사원이 없습니다.');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('결과가 두 건 이상입니다. 조건을 좁혀 주세요.');
END;
/
- NO_DATA_FOUND: 결과가 0건일 때 자동 발생.
- TOO_MANY_ROWS: 결과가 2건 이상일 때 자동 발생.
- 여러 행을 처리하려면 커서(5강)를 사용해야 합니다.
💻 PL/SQL 안에서 DML
BEGIN
-- INSERT
INSERT INTO emp_log(log_id, log_msg, log_dt)
VALUES (seq_log.NEXTVAL, '신규 사원 추가', SYSDATE);
-- UPDATE
UPDATE emp
SET sal = sal * 1.1
WHERE deptno = 20;
-- DELETE
DELETE FROM emp_log
WHERE log_dt < SYSDATE - 30; -- 30일 이전 로그 삭제
COMMIT; -- 트랜잭션 확정
DBMS_OUTPUT.PUT_LINE('처리 완료');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 오류 시 전체 취소
DBMS_OUTPUT.PUT_LINE('오류 발생, 롤백: ' || SQLERRM);
END;
/
COMMIT/ROLLBACK은 PL/SQL 블록 안에서 명시적으로 실행합니다. 블록이 정상 종료해도 자동 커밋되지 않습니다.
📖 암시적 커서와 커서 속성
DML(INSERT/UPDATE/DELETE) 또는 SELECT INTO를 실행하면 오라클은 내부적으로 암시적 커서(Implicit Cursor)를 자동 생성합니다. 이 커서의 속성으로 마지막 SQL의 결과를 확인할 수 있습니다.
BEGIN
UPDATE emp
SET sal = sal + 200
WHERE deptno = 30;
-- DML 직후 암시적 커서 속성 확인
IF SQL%FOUND THEN -- 한 건 이상 영향을 받았으면 TRUE
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || '건 업데이트되었습니다.');
ELSE
DBMS_OUTPUT.PUT_LINE('업데이트된 행이 없습니다.');
END IF;
COMMIT;
END;
/
주요 암시적 커서 속성:
SQL%FOUND : 마지막 SQL이 1건 이상 영향을 미쳤으면 TRUE
SQL%NOTFOUND : 영향을 미친 행이 없으면 TRUE
SQL%ROWCOUNT : 영향을 받은 행 수(숫자)
SQL%ISOPEN : 암시적 커서는 항상 FALSE (자동 닫힘)
⚠️ 주의사항
- SELECT INTO는 반드시 정확히 한 행만 반환해야 합니다. 집계가 없는 SELECT에 WHERE 조건이 느슨하면 TOO_MANY_ROWS가 납니다. 여러 행이 예상된다면 커서(5강)를 쓰세요.
- COMMIT을 행마다 실행하면
log file sync대기가 폭증합니다. 가능하면 일괄 처리 후 한 번 COMMIT하세요. - ROLLBACK은 해당 트랜잭션의 모든 DML을 취소합니다. SAVEPOINT를 활용하면 일부만 롤백할 수 있습니다.
💡 팁
- 암시적 커서 속성은 다음 SQL이 실행되면 덮어써집니다. DML 바로 다음 줄에서 확인하세요.
- SELECT INTO 결과가 1건인지 보장할 수 없을 때는 EXCEPTION 섹션에 NO_DATA_FOUND, TOO_MANY_ROWS를 항상 처리하는 습관을 들이세요.