프로그래밍에서 중요한 건 두 가지야: 무슨 일이 일어나고 있는지 이해하는 것(특히 뭔가 꼬였을 때!) 그리고 쓸모 있는 데이터를 반환하는 것. PL/pgSQL에서는 이게 더 중요해, 왜냐면 서버 쪽에서 돌아가니까 디버깅이 항상 쉽진 않거든. 그래서 내장 도구들이 도움을 줘:
RAISE NOTICE는 함수 실행 중에 메시지를 출력하는 방법이야. JavaScript의 console.log나 Python의 print랑 비슷하다고 생각하면 돼. 변수 값, 현재 실행 상태, 아니면 그냥 미래의 나한테 "안녕" 하고 싶을 때 쓸 수 있어.
RETURN QUERY는 데이터 세트(예를 들면 테이블 전체나 복잡한 쿼리 결과)를 반환하는 방법이야. 이걸로 PL/pgSQL 함수가 진짜 SQL 쿼리처럼 동작할 수 있어.
RAISE NOTICE 명령어
RAISE NOTICE는 함수 실행 중에 메시지를 화면에 출력할 수 있게 해줘. 포맷은 이렇게 생겼어:
RAISE NOTICE '메시지: %', 값;
%는 변수 자리에 들어가는 placeholder야, C의printf랑 비슷해.- 메시지 텍스트 뒤에 변수들을 나열해서 넣을 수 있어.
사용 예시
예를 들어, 여러 그룹에 있는 학생 수를 세는 함수를 만든다고 해보자. 중간중간 값이 잘 나오는지 확인하고 싶을 때 쓸 수 있어.
CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
group_name TEXT;
student_count INT;
BEGIN
FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
SELECT COUNT(*) INTO student_count
FROM students WHERE group_name = group_name;
-- 결과 출력
RAISE NOTICE '그룹: %, 학생 수: %', group_name, student_count;
END LOOP;
END;
$$ LANGUAGE plpgsql;
이 함수를 호출하면:
SELECT count_students_in_groups();
로그에서 이런 메시지를 볼 수 있어:
NOTICE: 그룹: 수학, 학생 수: 30
NOTICE: 그룹: 철학, 학생 수: 25
NOTICE: 그룹: 생물학, 학생 수: 18
이 함수는 아무것도 반환하지 않아(RETURNS VOID로 만들었으니까), 하지만 RAISE NOTICE로 반복문이 어떻게 돌아가는지 볼 수 있지.
RAISE로 쓸 수 있는 꿀팁
NOTICE 말고도 다른 메시지 레벨을 쓸 수 있어:
RAISE DEBUG— 추가 정보용(로그 레벨이 DEBUG일 때만 보여).RAISE INFO— 일반 정보용.RAISE WARNING— 경고 메시지용.RAISE EXCEPTION— 에러 발생용(이건 나중에 배울 거야).
디버깅할 땐 NOTICE나 DEBUG가 제일 좋아. 함수 실행을 멈추지 않으니까 편해.
RETURN QUERY 명령어: 데이터 반환, 프로답게!
RETURN QUERY는 PL/pgSQL에서 여러 행을 반환할 때 써. SQL 쿼리 결과를 함수에서 바로 반환할 수 있지. 문법은 이래:
RETURN QUERY <SQL-쿼리>;
여러 쿼리를 조합해서 쓸 수도 있어:
RETURN QUERY <SQL-쿼리 1>;
RETURN QUERY <SQL-쿼리 2>;
예시 1: RETURN QUERY 함수
특정 그룹의 학생 목록을 반환하는 함수를 만들어보자.
CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;
이제 이 함수를 호출해보자:
SELECT * FROM get_students_by_group('수학');
함수 테스트를 위해 먼저 students 테이블을 만들고 데이터를 넣자:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);
INSERT INTO students (name, group_name) VALUES
('Otto Song', '물리학'),
('Alex Lin', '수학'),
('Anna Vel', '수학'),
('Maria Chi', '역사');
결과:
| id | name |
|---|---|
| 2 | Alex Lin |
| 3 | Anna Vel |
보다시피, 함수가 일반 SQL 쿼리처럼 잘 동작하지.
예시 2: 여러 쿼리 합치기
여러 테이블에서 합쳐진 데이터를 반환하고 싶으면? 학생과 그들이 수강 중인 과목 목록을 반환해보자.
CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT s.name, c.name
FROM students s
JOIN enrollments e ON s.id = e.student_id
JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;
먼저 students, courses, enrollments 세 테이블을 만들고 데이터를 넣자:
-- 학생 테이블
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- 과목 테이블
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- 수강 기록 테이블(연결 테이블)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);
-- 학생 추가
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
-- 과목 추가
INSERT INTO courses (name) VALUES
('수학'),
('물리학'),
('역사');
-- 수강 기록 추가
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> 물리학
(2, 1), -- Alex -> 수학
(3, 1), -- Anna -> 수학
(4, 3); -- Maria -> 역사
이제 함수 호출:
SELECT * FROM get_students_and_courses();
결과는 이렇게 나와:
| student_name | course_name |
|---|---|
| Otto Song | 물리학 |
| Alex Lin | 수학 |
| Anna Vel | 수학 |
| Maria Chi | 역사 |
함수가 세 테이블에서 데이터를 잘 합쳐서, 어떤 학생이 어떤 과목을 듣는지 보여줘.
RAISE NOTICE와 RETURN QUERY 같이 쓰기
가끔 RETURN QUERY랑 RAISE NOTICE를 한 함수에서 같이 쓰면, 함수 실행 흐름을 확인하면서 중간 결과도 볼 수 있어.
아래는 학생 데이터를 반환하면서 동시에 메시지로 진행 상황을 보여주는 함수 예시야:
CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
count_students INT;
BEGIN
-- 학생 수 세기
SELECT COUNT(*) INTO count_students FROM students;
RAISE NOTICE '전체 학생 수: %', count_students;
-- 학생 데이터 반환
RETURN QUERY
SELECT id, name FROM students;
RAISE NOTICE '함수 실행 끝!';
END;
$$ LANGUAGE plpgsql;
students 테이블이 아직 없다면, 만들고 데이터도 넣자:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
이제 함수 호출:
SELECT * FROM debug_students();
데이터와 메시지를 동시에 볼 수 있어:
| student_id | student_name |
|---|---|
| 1 | Otto Song |
| 2 | Alex Lin |
| 3 | Anna Vel |
| 4 | Maria Chi |
콘솔 메시지 출력:
NOTICE: 전체 학생 수: 4
NOTICE: 함수 실행 끝!
자주 하는 실수들
RAISE NOTICE에서 변수 실수: 변수를 선언 안 했거나 이름을 잘못 쓰면 variable does not exist 에러가 나와. 항상 변수 선언이 제대로 됐는지 확인하자.
반환 타입 실수: RETURN QUERY를 쓰는데 함수 만들 때 RETURNS TABLE을 안 쓰면 PostgreSQL이 에러를 뱉어. 반환 타입이 실제 반환 데이터랑 맞는지 꼭 확인!
RAISE에서 placeholder 실수: placeholder % 개수랑 변수 개수가 다르면 에러가 나와. 예를 들어:
RAISE NOTICE '값: %, %', value1;
이건 두 번째 변수가 없어서 에러가 나.
GO TO FULL VERSION