2026년 07월 31일 | DBMS Error 가이드
이 글에서 다루는 내용
0100C 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
0100C dynamic result sets returned 는?
PostgreSQL 에러 코드 0100C는 dynamic_result_sets_returned 경고(Warning)로, SQL 저장 프로시저(Stored Procedure)가 호출자(caller)에게 반환할 것으로 선언된 것보다 더 많은 동적 결과 집합(dynamic result sets)을 반환할 때 발생합니다. 이 에러는 엄밀히 말하면 치명적인 오류(error)가 아닌 경고(warning) 수준의 메시지이며, SQL 표준과의 호환성을 위해 PostgreSQL이 발생시킵니다. 주로 PL/pgSQL 또는 PL/Python, PL/Perl 등의 언어로 작성된 프로시저에서 RESULT SETS 절을 잘못 선언하거나, 프로시저 내부 로직이 변경되어 실제 반환되는 결과 집합 수와 선언된 수가 일치하지 않을 때 나타납니다.
주요 발생 원인
1. RESULT SETS 선언 값과 실제 반환 결과 집합 수 불일치
가장 빈번하게 발생하는 원인으로, 프로시저를 처음 작성할 때 RESULT SETS N으로 선언해 두었지만, 이후 로직 변경으로 인해 실제로 반환되는 커서나 결과 집합이 늘어나는 경우입니다. PostgreSQL은 SQL/PSM(Persistent Stored Modules) 표준을 따르기 위해 프로시저 시그니처에 반환할 결과 집합 수를 명시할 수 있도록 지원하며, 이 값과 실제 실행 결과가 다르면 0100C 경고를 발생시킵니다. 특히 대규모 팀에서 코드 리뷰 없이 프로시저 본문만 수정하고 시그니처는 업데이트하지 않는 경우에 자주 나타납니다.
2. 조건 분기(IF/CASE)에 따른 가변적인 결과 집합 반환
프로시저 내부에서 IF나 CASE 조건에 따라 반환하는 결과 집합의 수가 달라지는 경우에도 이 경고가 발생할 수 있습니다. 예를 들어 특정 파라미터 값에 따라 하나의 결과 집합을 반환할 수도 있고, 두 개를 반환할 수도 있는 경우, 선언된 RESULT SETS 값이 어느 한쪽과만 일치하면 나머지 경우에서 경고가 발생합니다. 이런 패턴은 동적 쿼리(dynamic query)를 많이 활용하는 리포트 생성 프로시저에서 자주 볼 수 있습니다.
3. 마이그레이션 또는 외부 도구 자동 변환 시 선언 누락
Oracle, DB2, SQL Server 등 타 DBMS에서 PostgreSQL로 마이그레이션할 때, 자동 변환 도구가 RESULT SETS 절을 잘못 번역하거나 누락시키는 경우가 있습니다. 또한 ORM(Object Relational Mapper) 또는 자동 코드 생성 도구가 프로시저를 생성할 때 기본값으로 RESULT SETS 1을 넣어 두었는데, 실제 로직에서 여러 개의 커서를 열거나 여러 SELECT를 반환하는 경우도 해당됩니다. 이 경우 개별 프로시저를 하나씩 검토해야 하므로 운영 환경에서 발견 시 수정 비용이 큽니다.
해결 방법
원인 1 해결: RESULT SETS 선언 값 수정
프로시저 정의에서 RESULT SETS 값을 실제 반환되는 결과 집합 수에 맞게 수정합니다.
-- 기존 잘못된 프로시저 (RESULT SETS 1로 선언되어 있으나 실제로는 2개 반환)
CREATE OR REPLACE PROCEDURE get_employee_data(dept_id INT)
LANGUAGE SQL
RESULT SETS 1 -- 잘못된 선언
AS $$
-- 첫 번째 결과 집합
SELECT employee_id, employee_name, salary
FROM employees
WHERE department_id = dept_id;
-- 두 번째 결과 집합
SELECT department_id, department_name, budget
FROM departments
WHERE department_id = dept_id;
$$;
-- 수정된 프로시저 (RESULT SETS 2로 변경)
CREATE OR REPLACE PROCEDURE get_employee_data(dept_id INT)
LANGUAGE SQL
RESULT SETS 2 -- 올바른 선언
AS $$
SELECT employee_id, employee_name, salary
FROM employees
WHERE department_id = dept_id;
SELECT department_id, department_name, budget
FROM departments
WHERE department_id = dept_id;
$$;
원인 2 해결: 조건 분기 로직 리팩토링
가변적인 결과 집합 반환 대신, 단일 결과 집합으로 통합하거나 별도 프로시저로 분리합니다.
-- 문제가 있는 패턴: 조건에 따라 결과 집합 수가 달라짐
CREATE OR REPLACE PROCEDURE get_report(report_type VARCHAR)
LANGUAGE plpgsql
RESULT SETS 1
AS $$
BEGIN
IF report_type = 'SIMPLE' THEN
-- 결과 집합 1개 반환
RETURN QUERY SELECT id, name FROM employees;
ELSIF report_type = 'DETAILED' THEN
-- 결과 집합 2개 반환 → 0100C 경고 발생!
RETURN QUERY SELECT id, name FROM employees;
RETURN QUERY SELECT dept_id, dept_name, budget FROM departments;
END IF;
END;
$$;
-- 해결책 1: 최대 결과 집합 수로 RESULT SETS 선언 수정
CREATE OR REPLACE PROCEDURE get_report(report_type VARCHAR)
LANGUAGE plpgsql
RESULT SETS 2 -- 최대값으로 선언
AS $$
BEGIN
IF report_type = 'SIMPLE' THEN
RETURN QUERY SELECT id, name FROM employees;
-- 두 번째 결과 집합은 빈 결과로 반환하거나 로직상 제외
ELSIF report_type = 'DETAILED' THEN
RETURN QUERY SELECT id, name FROM employees;
RETURN QUERY SELECT dept_id, dept_name, budget FROM departments;
END IF;
END;
$$;
-- 해결책 2: 프로시저를 분리하여 단일 책임 원칙 적용
CREATE OR REPLACE PROCEDURE get_simple_report()
LANGUAGE plpgsql
RESULT SETS 1
AS $$
BEGIN
RETURN QUERY SELECT id, name FROM employees;
END;
$$;
CREATE OR REPLACE PROCEDURE get_detailed_report()
LANGUAGE plpgsql
RESULT SETS 2
AS $$
BEGIN
RETURN QUERY SELECT id, name FROM employees;
RETURN QUERY SELECT dept_id, dept_name, budget FROM departments;
END;
$$;
원인 3 해결: 마이그레이션 후 프로시저 점검 스크립트
마이그레이션 이후 모든 프로시저의 RESULT SETS 선언을 일괄 점검하는 방법입니다.
-- pg_proc 카탈로그를 활용해 프로시저 목록 조회
SELECT
n.nspname AS schema_name,
p.proname AS procedure_name,
p.pronargs AS argument_count,
pg_get_function_arguments(p.oid) AS arguments,
p.prokind AS procedure_kind -- 'p'이면 프로시저
FROM
pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE
p.prokind = 'p' -- 프로시저만 조회
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY
n.nspname, p.proname;
-- 특정 프로시저의 정의 전체 확인
SELECT pg_get_functiondef(oid)
FROM pg_proc
WHERE proname = 'get_employee_data'
AND prokind = 'p';
-- 경고 레벨 설정을 통해 0100C 경고를 로그로 캡처
SET client_min_messages = 'WARNING';
-- 프로시저 호출 후 경고 확인
CALL get_employee_data(10);
예방 방법
1. 프로시저 변경 시 단위 테스트 및 시그니처 검토 의무화
프로시저의 본문(body)을 수정할 때 반드시 RESULT SETS 선언도 함께 검토하도록 개발 프로세스에 포함시켜야 합니다. CI/CD 파이프라인에 프로시저 호출 후 경고 메시지를 캡처하는 테스트 스텝을 추가하고, 경고가 발생하면 배포를 차단하도록 설정합니다. 아래와 같이 pgTAP을 활용한 간단한 프로시저 테스트로 경고 발생 여부를 사전에 확인할 수 있습니다.
-- pgTAP을 활용한 프로시저 검증 예시
BEGIN;
SELECT plan(1);
-- 프로시저 호출 시 경고 없이 정상 완료되는지 확인
SELECT lives_ok(
$$ CALL get_employee_data(10) $$,
'get_employee_data should execute without warnings'
);
SELECT * FROM finish();
ROLLBACK;
2. 프로시저 설계 단계에서 결과 집합 수 고정화
가능하면 프로시저가 반환하는 결과 집합의 수를 설계 단계에서 고정시키고, 가변적인 결과 집합 반환이 필요한 경우에는 OUT 파라미터나 테이블 반환 함수(Table-Returning Function)를 활용합니다. 조건에 따라 다른 데이터를 반환해야 한다면, 단일 결과 집합 안에서 type_flag 컬럼 등을 추가하여 구분하는 방식이 더 안정적이고 유지보수가 쉽습니다.
-- 권장 패턴: 단일 결과 집합에 구분 컬럼 추가
CREATE OR REPLACE FUNCTION get_unified_report(report_type VARCHAR)
RETURNS TABLE(
record_type VARCHAR,
id INT,
name VARCHAR,
extra_info VARCHAR
)
LANGUAGE plpgsql
AS $$
BEGIN
IF report_type IN ('SIMPLE', 'DETAILED') THEN
RETURN QUERY
SELECT 'EMPLOYEE'::VARCHAR, e.id, e.name, e.salary::VARCHAR
FROM employees e;
END IF;
IF report_type = 'DETAILED' THEN
RETURN QUERY
SELECT 'DEPARTMENT'::VARCHAR, d.dept_id, d.dept_name, d.budget::VARCHAR
FROM departments d;
END IF;
END;
$$;
-- 호출 예시
SELECT * FROM get_unified_report('DETAILED');
관련 에러
01000(warning): 일반적인 SQL 경고의 부모 클래스로,0100C는 이 카테고리에 속합니다.01P01(deprecated_feature): 더 이상 권장되지 않는 기능을 사용할 때 발생하는 경고로, 마이그레이션 작업 시0100C와 함께 자주 등장합니다.42P13(invalid_function_definition): 함수 또는 프로시저 정의 자체가 유효하지 않을 때 발생하며,RESULT SETS절의 문법 오류 시 이 에러로 이어질 수 있습니다.0A000(feature_not_supported): 특정 PostgreSQL 버전에서 지원하지 않는RESULT SETS관련 기능을 사용하려 할 때 발생할 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.