컴퓨터과학 챕터 3 약 6분

Ch3. SQLD 자격증 — 절차형 SQL과 데이터 모델링

O
OIYO 편집부 기여자
3/4

절차형 SQL 개요

SQL은 기본적으로 비절차적 언어입니다 — 무엇을 할지만 지정하고, 어떻게 할지는 DBMS가 결정합니다.

하지만 **절차형 SQL(Procedural SQL)**은 조건문·반복문·변수를 사용해 프로그래밍처럼 작성할 수 있습니다.

구분언어
OraclePL/SQL (Procedural Language/SQL)
SQL ServerT-SQL (Transact-SQL)
MySQLStored Procedure (유사 문법)

PL/SQL 기본 구조

DECLARE
    -- 변수 선언 영역
    v_name   VARCHAR2(50);
    v_salary NUMBER(10,2) := 0;
    v_count  NUMBER;
BEGIN
    -- 실행 영역
    SELECT name, salary
    INTO v_name, v_salary
    FROM employees
    WHERE emp_id = 101;
    
    DBMS_OUTPUT.PUT_LINE('이름: ' || v_name);
    DBMS_OUTPUT.PUT_LINE('급여: ' || v_salary);
EXCEPTION
    -- 예외 처리 영역
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('데이터 없음');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('오류 발생: ' || SQLERRM);
END;
/

변수와 데이터 타입

DECLARE
    -- 직접 타입 지정
    v_id     NUMBER := 1;
    v_name   VARCHAR2(100) := '홍길동';
    v_date   DATE := SYSDATE;
    v_flag   BOOLEAN := TRUE;
    
    -- %TYPE: 테이블 컬럼 타입 자동 참조 (권장)
    v_emp_name employees.name%TYPE;
    v_emp_sal  employees.salary%TYPE;
    
    -- %ROWTYPE: 행 전체 타입
    v_emp_row  employees%ROWTYPE;
BEGIN
    SELECT * INTO v_emp_row
    FROM employees WHERE emp_id = 101;
    
    DBMS_OUTPUT.PUT_LINE(v_emp_row.name || ': ' || v_emp_row.salary);
END;

조건문

IF-THEN-ELSIF-ELSE

BEGIN
    IF v_salary >= 8000000 THEN
        DBMS_OUTPUT.PUT_LINE('고액연봉');
    ELSIF v_salary >= 5000000 THEN
        DBMS_OUTPUT.PUT_LINE('중간연봉');
    ELSE
        DBMS_OUTPUT.PUT_LINE('신입연봉');
    END IF;
END;

CASE 문

DECLARE
    v_grade CHAR(1) := 'A';
BEGIN
    CASE v_grade
        WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('우수');
        WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('양호');
        WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('보통');
        ELSE           DBMS_OUTPUT.PUT_LINE('미흡');
    END CASE;
END;

반복문

LOOP (기본)

DECLARE
    v_i NUMBER := 1;
BEGIN
    LOOP
        DBMS_OUTPUT.PUT_LINE(v_i);
        v_i := v_i + 1;
        EXIT WHEN v_i > 5;  -- 탈출 조건
    END LOOP;
END;

WHILE LOOP

DECLARE
    v_i NUMBER := 1;
BEGIN
    WHILE v_i <= 5 LOOP
        DBMS_OUTPUT.PUT_LINE(v_i);
        v_i := v_i + 1;
    END LOOP;
END;

FOR LOOP

BEGIN
    FOR i IN 1..5 LOOP  -- 1부터 5까지
        DBMS_OUTPUT.PUT_LINE(i);
    END LOOP;
    
    FOR i IN REVERSE 5..1 LOOP  -- 역순
        DBMS_OUTPUT.PUT_LINE(i);
    END LOOP;
END;

커서(Cursor)

여러 행을 반환하는 쿼리 결과를 한 행씩 처리할 때 사용합니다.

DECLARE
    CURSOR emp_cursor IS
        SELECT name, salary FROM employees
        WHERE dept_id = 10;
    
    v_name   employees.name%TYPE;
    v_salary employees.salary%TYPE;
BEGIN
    OPEN emp_cursor;
    
    LOOP
        FETCH emp_cursor INTO v_name, v_salary;
        EXIT WHEN emp_cursor%NOTFOUND;  -- 더 이상 행 없을 때 종료
        DBMS_OUTPUT.PUT_LINE(v_name || ': ' || v_salary);
    END LOOP;
    
    CLOSE emp_cursor;
END;

커서 속성:

속성의미
%FOUND마지막 FETCH가 행을 반환했으면 TRUE
%NOTFOUND마지막 FETCH가 행을 반환 못 했으면 TRUE
%ROWCOUNT지금까지 FETCH한 행 수
%ISOPEN커서가 열려 있으면 TRUE

저장 프로시저와 함수

저장 프로시저 (Stored Procedure)

-- 생성
CREATE OR REPLACE PROCEDURE raise_salary(
    p_emp_id  IN  NUMBER,
    p_rate    IN  NUMBER,
    p_new_sal OUT NUMBER
)
IS
BEGIN
    UPDATE employees
    SET salary = salary * (1 + p_rate/100)
    WHERE emp_id = p_emp_id;
    
    SELECT salary INTO p_new_sal
    FROM employees WHERE emp_id = p_emp_id;
    
    COMMIT;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RAISE_APPLICATION_ERROR(-20001, '직원 없음');
END raise_salary;

-- 실행
DECLARE
    v_new_sal NUMBER;
BEGIN
    raise_salary(101, 10, v_new_sal);
    DBMS_OUTPUT.PUT_LINE('새 급여: ' || v_new_sal);
END;

함수(Function)와 프로시저 차이

구분프로시저함수
반환값RETURN 없음 (OUT 파라미터 사용)RETURN 있음 (반드시 반환)
SQL에서 호출불가가능 (SELECT get_salary(101) FROM dual)
DML 사용가능제한적

트리거(Trigger)

특정 이벤트(INSERT/UPDATE/DELETE) 발생 시 자동 실행되는 코드입니다.

CREATE OR REPLACE TRIGGER salary_audit
BEFORE UPDATE OF salary ON employees
FOR EACH ROW
BEGIN
    IF :NEW.salary < :OLD.salary THEN
        RAISE_APPLICATION_ERROR(-20002, '급여 삭감 불가');
    END IF;
    
    INSERT INTO salary_log(emp_id, old_sal, new_sal, change_date)
    VALUES(:OLD.emp_id, :OLD.salary, :NEW.salary, SYSDATE);
END;

트리거 유형:

시점대상설명
BEFOREROW / STATEMENTDML 실행 전 동작
AFTERROW / STATEMENTDML 실행 후 동작
INSTEAD OFVIEW뷰에 대한 DML을 다른 동작으로 대체

데이터 모델링

3단계 설계 과정

개념적 설계 → 논리적 설계 → 물리적 설계
(E-R 다이어그램)  (릴레이션 스키마)  (테이블 정의)
단계도구결과물
개념적ERD엔티티·속성·관계 다이어그램
논리적정규화릴레이션 스키마 (정규형)
물리적DBMS 종류CREATE TABLE, 인덱스

정규화 (Normalization)

데이터 중복을 제거하고 일관성을 높이는 과정입니다.

제1정규형 (1NF)

조건: 모든 속성이 원자값(Atomic Value) — 반복 그룹 없음

위반 예:
학생ID | 이름 | 수강과목
1      | 홍길동 | 수학, 영어, 과학  ← 반복 그룹

1NF 적용:
학생ID | 이름 | 수강과목
1      | 홍길동 | 수학
1      | 홍길동 | 영어
1      | 홍길동 | 과학

제2정규형 (2NF)

조건: 1NF + 부분 함수 종속 제거 (복합 기본키에서 일부에만 종속되는 속성 분리)

제3정규형 (3NF)

조건: 2NF + 이행 함수 종속 제거 (비키 속성이 다른 비키 속성에 종속)

위반: 학번 → 학과코드 → 학과명  (학과명이 학번에 이행 종속)
3NF: 학생(학번, 학과코드) + 학과(학과코드, 학과명) 분리

BCNF (Boyce-Codd 정규형)

조건: 3NF + 모든 결정자가 후보키


ERD 표기법 (IE 표기법)

SQLD에서 자주 출제되는 ERD 읽기:

[학생] ─────< [수강] >───── [강좌]
  |              |               |
학번(PK)    학번(FK)         강좌코드(PK)
이름         강좌코드(FK)     강좌명

관계 표기:

  • | : 정확히 1개 (필수)
  • O : 0개 가능 (선택)
  • < : 여러 개 가능 (Many)

트랜잭션 (Transaction)

BEGIN TRANSACTION;

UPDATE accounts SET balance = balance - 100000 WHERE acc_id = 'A';
UPDATE accounts SET balance = balance + 100000 WHERE acc_id = 'B';

COMMIT;   -- 정상 완료 시 확정
-- 또는
ROLLBACK; -- 오류 시 전체 취소

ACID 속성:

속성설명
Atomicity (원자성)전부 실행 or 전부 취소
Consistency (일관성)트랜잭션 전후 DB 상태 일관 유지
Isolation (고립성)동시 실행 트랜잭션이 서로 간섭 않음
Durability (지속성)COMMIT된 결과는 영구 저장

실전 퀴즈 5문항

Q1. PL/SQL에서 %TYPE을 사용하는 이유로 가장 적절한 것은?

  • ① 더 빠른 실행 속도
  • ② 테이블 컬럼 타입 변경 시 자동 반영
  • ③ NULL 값 허용
  • ④ 커서 선언 가능

정답: ②


Q2. 트리거(Trigger)에 대한 설명으로 옳지 않은 것은?

  • ① 특정 이벤트 발생 시 자동 실행
  • ② BEFORE, AFTER, INSTEAD OF 유형이 있다
  • ③ 명시적으로 호출해야 실행된다
  • ④ :NEW, :OLD 로 변경 전후 값 참조 가능

정답: ③


Q3. 제3정규형(3NF) 위반의 예로 옳은 것은?

  • ① 반복 그룹이 존재하는 경우
  • ② 복합 키의 일부에만 종속되는 속성
  • ③ 비키 속성이 다른 비키 속성에 종속
  • ④ 모든 결정자가 후보키가 아닌 경우

정답: ③


Q4. ROLLBACK이 가능한 SQL 명령어는?

  • ① TRUNCATE
  • ② DROP
  • ③ DELETE
  • ④ ALTER

정답: ③


Q5. 저장 프로시저와 함수의 차이로 옳은 것은?

  • ① 프로시저는 SELECT에서 호출 가능
  • ② 함수는 반드시 값을 반환한다
  • ③ 프로시저는 DML 사용 불가
  • ④ 함수와 프로시저 모두 트리거로 사용 가능

정답: ②

O

OIYO 편집부

Content Editor

지식 인큐베이터이자 전문 콘텐츠 크리에이터. 경영, 경제, 법률 및 실생활에 유용한 실무/자격증 중심의 깊이 있는 정보를 연구하고 공유합니다.