이제 PL/pgSQL을 좀 더 깊게 파고들어보고, 본격적으로 써보자!
코드 블록
PL/pgSQL에서 코드 블록은 언어의 기본 빌딩 블록이야. 쉽게 말하면, 함수, 프로시저 등등의 마법이 다 이 블록 위에 얹혀 있는 거지. 블록은 로직 실행, 데이터 처리, 에러 핸들링 등등을 한 "컨테이너" 안에서 다 처리해줘.
PL/pgSQL 블록은 구조화되어 있고, 세 가지 주요 파트가 있어:
DECLARE: 변수 선언 (선택사항).BEGIN ... END: 메인 실행 블록, 여기서 로직이 돌아감.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;
$$;
이제 이걸 단계별로 뜯어보자.
DECLARE— 여기서 변수 선언하는 거야. 좋은 점은 PL/pgSQL이 PostgreSQL에서 쓸 수 있는 거의 모든 데이터 타입을 지원한다는 거!INTEGER같은 기본적인 것부터, 좀 특이한 JSONB까지. 변수를 선언하려면 이름, 데이터 타입, 그리고 필요하면 초기값을 지정하면 돼.
예시:
DECLARE
student_name TEXT; -- 학생 이름용 변수
course_count INT := 0; -- 초기값 0으로 설정
is_graduated BOOLEAN; -- 논리형 변수
변수는 course_count처럼 초기화할 수도 있고, 그냥 선언만 할 수도 있어.
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;
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;
GO TO FULL VERSION