CodeGym /행동 /SQL SELF /PL/pgSQL 문법의 기초

PL/pgSQL 문법의 기초

SQL SELF
레벨 49, 레슨 3
사용 가능

이제 PL/pgSQL을 좀 더 깊게 파고들어보고, 본격적으로 써보자!

코드 블록

PL/pgSQL에서 코드 블록은 언어의 기본 빌딩 블록이야. 쉽게 말하면, 함수, 프로시저 등등의 마법이 다 이 블록 위에 얹혀 있는 거지. 블록은 로직 실행, 데이터 처리, 에러 핸들링 등등을 한 "컨테이너" 안에서 다 처리해줘.

PL/pgSQL 블록은 구조화되어 있고, 세 가지 주요 파트가 있어:

  1. DECLARE: 변수 선언 (선택사항).
  2. BEGIN ... END: 메인 실행 블록, 여기서 로직이 돌아감.
  3. EXCEPTION: 에러 처리 (선택사항).

비유를 좋아한다면: 요리 레시피를 생각해봐. 레시피 텍스트는 재료 목록으로 시작할 수 있지만, 진짜 마법은 요리 과정에서 일어나지. PL/pgSQL로 치면:

  • DECLARE — 이건 재료 리스트 (변수들).
  • BEGIN ... END — 여기서 섞고, 굽고, 끓이고 다 하는 거야.
  • EXCEPTION — 뭔가 타버리면 대처하는 플랜.

PL/pgSQL 블록 문법

먼저 블록의 전체 구조, 즉 "뼈대"를 보자. 나중에 고기(아니면 비건 치즈라도 ㅋㅋ)를 붙여서 실제 로직을 넣을 거야.

DO $$
DECLARE
    -- 여기서 변수 선언
    student_count INT;
BEGIN
    -- 여기서 로직 실행
    SELECT COUNT(*) INTO student_count FROM students;
    RAISE NOTICE '학생 총 수: %', student_count;
EXCEPTION
    -- 여기서 에러 처리
    WHEN OTHERS THEN
        RAISE NOTICE '에러가 발생했어.';
END;
$$;

이제 이걸 단계별로 뜯어보자.

  1. DECLARE — 여기서 변수 선언하는 거야. 좋은 점은 PL/pgSQL이 PostgreSQL에서 쓸 수 있는 거의 모든 데이터 타입을 지원한다는 거! INTEGER 같은 기본적인 것부터, 좀 특이한 JSONB까지. 변수를 선언하려면 이름, 데이터 타입, 그리고 필요하면 초기값을 지정하면 돼.

예시:

DECLARE
    student_name TEXT;    -- 학생 이름용 변수
    course_count INT := 0; -- 초기값 0으로 설정
    is_graduated BOOLEAN; -- 논리형 변수

변수는 course_count처럼 초기화할 수도 있고, 그냥 선언만 할 수도 있어.

  1. BEGIN ... END — 메인 실행 블록.

이 부분이 실제 로직을 실행하는 곳이야. 여기서 할 수 있는 건:

  • SQL 쿼리 실행 (SELECT, INSERT 등).
  • 데이터 조작.
  • 제어문 사용 (IF, LOOP 등).
  • RAISE로 디버깅 메시지 출력.

예시:

BEGIN
    SELECT COUNT(*) INTO student_count FROM students;
    IF student_count > 0 THEN
        RAISE NOTICE '학생이 있어!';
    ELSE
        RAISE NOTICE '학생이 없어.';
    END IF;
END;
  1. EXCEPTION — 에러 처리 (선택사항).

블록 실행 중에 에러가 나면, EXCEPTION 섹션에서 그걸 잡아서 뭔가 할 수 있어. 예를 들어 메시지 출력이나 대체 코드 실행 등.

예시:

BEGIN
    SELECT COUNT(*) INTO student_count FROM non_existing_table; -- 에러!
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE '앗, 뭔가 잘못됐어!';
END;

실전 예시: 학생 수 세기

이제 모든 파트를 합쳐서 실제로 쓸만한 예제를 만들어보자. students 테이블에서 학생 수를 세고, 메시지를 출력하는 PL/pgSQL 블록을 작성해볼 거야.

DO $$
DECLARE
    total_students INT; -- 학생 수 저장용 변수
BEGIN
    -- 학생 수 세기
    SELECT COUNT(*) INTO total_students FROM students;

    -- 결과 메시지 출력
    RAISE NOTICE '학생 수: %', total_students;
EXCEPTION
    -- 예를 들어 테이블이 없을 때 등 에러 처리
    WHEN OTHERS THEN
        RAISE NOTICE '학생 수 세는 중 에러가 발생했어.';
END;
$$;

이 블록을 실행하면 콘솔에 메시지가 출력돼. 예를 들어: 학생 수: 42.

변수 사용의 특징

몇 가지 중요한 포인트를 짚어볼게:

변수에 값 할당하기. 변수에 값을 넣으려면 SELECT INTO 연산자를 쓰면 돼:

SELECT COUNT(*) INTO total_students FROM students;

변수 초기화. 선언할 때 값을 안 넣으면, 변수의 기본값은 NULL이야.

예시:

DECLARE
    my_var INT; -- 값은 NULL

RECORD 타입 변수. 이건 테이블에서 한 줄을 통째로 담을 수 있는 범용 변수 타입이야. 예시:

DECLARE
    student RECORD;
BEGIN
    SELECT * INTO student FROM students WHERE id = 1;
    RAISE NOTICE '학생 이름: %, 나이: %', student.name, student.age;
END;

예시: 학생의 수강 과목 수 세기

이제 실전 문제! 학생이 몇 과목을 듣고 있는지 세고, 결과를 출력해보자.

DO $$
DECLARE
    student_id INT := 1;   -- 학생 ID
    course_count INT;      -- 과목 수 저장용 변수
BEGIN
    -- 과목 수 세기
    SELECT COUNT(*) INTO course_count
    FROM enrollments
    WHERE student_id = student_id;

    -- 메시지 출력
    RAISE NOTICE '학생 ID %는 %개의 과목을 듣고 있어.', student_id, course_count;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE '학생 ID % 처리 중 에러 발생', student_id;
END;
$$;

이 블록은 student_id만 바꿔주면 여러 학생에 대해 과목 수를 쉽게 확인할 수 있어.

에러와 예방법

PL/pgSQL이 아직은 전자레인지 속의 작은 핫도그처럼 느껴진다면, 그거 완전 정상임 ㅋㅋ. 처음엔 흔한 실수도 많이 하게 돼. 몇 가지 예시를 볼게:

변수 선언 안 함. DECLARE로 변수를 선언 안 하면, PL/pgSQL이 "변수가 존재하지 않는다"고 에러를 뱉어.

NULL을 값으로 쓸 때. 변수는 선언만 하고 값을 안 넣으면 NULL이 돼. 이게 예상치 못한 동작을 부를 수 있어. 예를 들어:

IF my_var = NULL THEN -- 작동 안 함!

IS NULL을 써야 해:

IF my_var IS NULL THEN

EXCEPTION 섹션 잘못 쓰기. 가끔 개발자들이 (WHEN OTHERS)로 모든 에러를 잡아놓고, 아무것도 안 써. 이러면 진짜 문제를 못 찾을 수도 있어. 에러 메시지는 꼭 남기자:

RAISE NOTICE '에러: %', SQLERRM;
2
과제
SQL SELF, 레벨 49, 레슨 3
잠금
테이블의 레코드 개수 세기
테이블의 레코드 개수 세기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION