노트

Oracle PL/SQL

Oracle PL/SQL (Procedural Language extensions to SQL)

백엔드#db · 연결된 개념 2개

쉽게 말하면

PL/SQL은 재료를 매번 집으로 들고 와 요리하지 않고 농장 안 작업장에서 바로 손질하듯, 조건문·반복문이 든 로직을 오라클 DB 안에서 데이터 가까이 돌리는 언어예요. 대량 처리할 때 왕복이 줄죠.

비유가 깨지는 곳 편한 만큼 업무 로직이 DB 안에 흩어져 테스트·버전 관리·배포가 어려워지고 오라클에 묶여요. 트리거처럼 자동으로 연쇄 실행되는 동작은 코드만 봐서는 안 보여 놀라기 쉬워요.

PL/SQL(Procedural Language/SQL)은 Oracle이 SQL에 변수·조건문·반복문·예외 처리를 더한 절차형 언어(procedural language)다. DB 안에서 함수·프로시저(stored procedure)·트리거(trigger)를 만들어 로직을 데이터 가까이에서 돌린다. 다른 DB에도 비슷한 것(PostgreSQL의 PL/pgSQL 등)이 있지만 문법은 제각각이다.

블록 구조

SET SERVEROUTPUT ON
DECLARE
  v_name  emp.ename%TYPE;      -- 컬럼 타입을 그대로 참조
  v_row   emp%ROWTYPE;         -- 행 전체를 담는 레코드
BEGIN
  SELECT ename INTO v_name FROM emp WHERE empno = 7369;   -- 정확히 한 행이어야 함
  DBMS_OUTPUT.PUT_LINE(v_name);
EXCEPTION
  WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('없음');
END;
/
  • SELECT ... INTO는 결과가 0행이거나 여러 행이면 예외가 난다
  • %TYPE·%ROWTYPE은 테이블이 바뀌어도 따라가지만, 코드만 봐서는 타입을 알기 어렵다
  • 배열 대신 TABLE OF ... INDEX BY 컬렉션, 여러 타입을 묶는 RECORD를 쓴다

커서

여러 행을 하나씩 처리하는 포인터(cursor)다.

  • 암시적 커서(implicit cursor): DML(Data Manipulation Language)을 실행하면 자동으로 생긴다. SQL%ROWCOUNT로 영향받은 행 수를 본다
  • 명시적 커서(explicit cursor): 선언 → OPEN → FETCH 반복(EXIT WHEN c%NOTFOUND) → CLOSE. 닫지 않으면 자원이 샌다
  • 커서 FOR 루프: FOR r IN (SELECT ...) LOOP ... END LOOP; 열기·인출·닫기를 알아서 해 준다

함수와 프로시저

  • FUNCTION: 값을 반환하고 SQL 안에서 호출할 수 있다
  • PROCEDURE: 반환값 대신 OUT 파라미터로 결과를 내보낸다. 여러 행은 SYS_REFCURSOR를 OUT으로 열어 넘기고, 프로시저 안에서 FETCH하지 않는다(호출자가 읽는다)
  • PACKAGE: 관련 함수·프로시저를 명세(spec)와 본문(body)으로 묶는다
  • TRIGGER: 테이블의 INSERT·UPDATE·DELETE 전후에 자동 실행된다. :OLD·:NEW로 변경 전후 값을 본다
  • 스케줄링: 예전 DBMS_JOB보다 DBMS_SCHEDULER가 권장된다

언제 쓰나

데이터를 대량으로 옮기는 배치처럼 왕복을 줄여야 할 때 강하다. 반면 업무 로직이 DB에 흩어지면 테스트·버전 관리·배포가 어려워지고 특정 DB에 묶인다. 트리거의 숨은 연쇄 동작은 최소 놀람을 깨기 쉽다. 자바에서는 JDBC(Java Database Connectivity)의 CallableStatement로 호출한다(JDBC와 JdbcTemplate).

출처: Oracle 문서: Overview of PL/SQL · PL/SQL Static SQL(커서)

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • JPQL과 @Query

    JPQL(Jakarta Persistence Query Language)은 테이블이 아니라 엔티티와 필드를 대상으로 쓰는 JPA의 객체 지향 쿼리 언어다. 실행할 때 연결된 DB의 SQL로 번역된다. Spring Data에서는 @Query로 리포지터리 메서드에 직접 붙인다.

  • PostgreSQL 내부 동작(MVCC·VACUUM·WAL·플래너)

    PostgreSQL은 행을 덮어쓰지 않고 새 버전을 쓰며(MVCC), 옛 버전은 VACUUM이 치우고, 커밋은 WAL에 남는 순간 확정되며, 플래너는 통계만 보고 계획을 고른다. 운영 이슈 대부분이 이 넷에서 나온다.

  • 재귀

    함수가 자기 자신을 다시 호출해 문제를 푸는 방식. 같은 함수를 점점 작은 입력으로 부르다가 더 나눌 필요가 없는 지점(기저 조건, Base Case)에서 멈춘다.

  • DB 인덱스와 트레이드오프

    DB 인덱스는 특정 컬럼 값으로 행을 빨리 찾도록 테이블 옆에 따로 유지하는 보조 자료구조(auxiliary data structure)다. 관계형 DB의 기본 인덱스는 정렬된 균형 트리(B-tree 계열)라서, 전체를 훑지 않고 트리를 따라 내려가 원하는 행에 닿는다.

  • 리팩터링 기법 카탈로그

    리팩터링 기법을 무엇을 정리하는지에 따라 묶어 본 지도. 기법마다 거의 항상 반대 방향 기법이 짝으로 있어서(추출↔인라인, 올리기↔내리기) 상황에 따라 양쪽으로 오간다. 아래 묶음은 Refactoring.Guru 카탈로그(1판 기반)의 분류를 따랐고, 기법 이름은 2판 기준으로 적었다.

보기 옵션