CodeGym /행동 /SQL SELF /RAISE NOTICE, RETURN QUERY 연산자

RAISE NOTICE, RETURN QUERY 연산자

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

프로그래밍에서 중요한 건 두 가지야: 무슨 일이 일어나고 있는지 이해하는 것(특히 뭔가 꼬였을 때!) 그리고 쓸모 있는 데이터를 반환하는 것. 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 — 에러 발생용(이건 나중에 배울 거야).

디버깅할 땐 NOTICEDEBUG가 제일 좋아. 함수 실행을 멈추지 않으니까 편해.

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 NOTICERETURN QUERY 같이 쓰기

가끔 RETURN QUERYRAISE 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;

이건 두 번째 변수가 없어서 에러가 나.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION