Oracle ORA-00996 오류 원인과 해결 방법 완벽 가이드

ORA-00996
2026년 06월 24일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-00996 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-00996 the concatenate operator is ||, not | 는?

ORA-00996 에러는 Oracle SQL 또는 PL/SQL 코드에서 문자열 연결(concatenate) 연산자를 잘못 사용했을 때 발생하는 문법 오류입니다. Oracle에서 문자열을 이어 붙이는 올바른 연산자는 파이프 기호 두 개(||)인데, 단일 파이프(|) 하나만 입력했을 때 Oracle 파서가 이를 인식하지 못하고 이 에러를 반환합니다. 주로 다른 프로그래밍 언어(Java, JavaScript, PHP 등)에서는 |가 비트 OR 연산자나 문자열 연결에 사용되는 경우가 있어, 개발자들이 습관적으로 단일 파이프를 사용하다가 발생하는 실수입니다.


주요 발생 원인

  • 단일 파이프(|) 사용으로 인한 문법 오류

가장 흔한 원인으로, 개발자가 Oracle의 문자열 연결 연산자가 ||임을 인지하지 못하거나 타이핑 실수로 파이프를 하나만 입력하는 경우입니다. 특히 키보드 자판 배열상 | 키를 연속으로 두 번 누르는 것이 익숙하지 않은 개발자에게서 자주 발생하며, 코드 리뷰 없이 배포되는 쿼리에서 많이 발견됩니다.

  • 타 DBMS 또는 프로그래밍 언어에서 마이그레이션 시 연산자 혼용

MySQL, PostgreSQL, MS SQL Server, 또는 Java/Python 등의 언어에서 Oracle로 코드를 이전할 때 각 플랫폼 고유의 문자열 처리 방식이 혼재되면서 발생합니다. 예를 들어, 일부 언어에서는 + 연산자나 단일 | 를 문자열 연결에 사용하는 경우가 있으며, 이 코드를 Oracle 환경에 그대로 가져오면 ORA-00996 에러가 발생합니다.

  • 동적 SQL 생성 시 문자열 조합 오류

PL/SQL 내에서 동적 SQL 문자열을 프로그램적으로 조합할 때, 변수 값이나 외부 입력값에 잘못된 연산자가 포함되어 최종 SQL 문자열에 단일 |가 들어가는 경우입니다. 특히 외부 애플리케이션에서 SQL 쿼리를 문자열로 생성하여 Oracle에 전달하는 구조에서, 중간 처리 로직의 버그로 인해 연산자가 누락되거나 잘못 조합되는 상황이 발생합니다.


해결 방법

원인 1: 단일 파이프 → 이중 파이프로 수정

잘못된 예시 (에러 발생):

-- ORA-00996 발생
SELECT first_name | ' ' | last_name AS full_name
FROM employees;

올바른 예시 (수정 후):

-- 정상 실행
SELECT first_name || ' ' || last_name AS full_name
FROM employees;

추가 예시 – 여러 컬럼 연결:

-- 부서명과 직급을 연결하여 표시
SELECT department_name || ' - ' || job_id AS dept_job_info
FROM departments d
JOIN employees e ON d.department_id = e.department_id
WHERE ROWNUM <= 10;

원인 2: 타 DBMS 마이그레이션 시 수정

MySQL 스타일 (Oracle에서 에러 발생):

-- MySQL에서는 CONCAT() 또는 다른 방식 사용
-- 아래는 Oracle에서 ORA-00996 발생 가능
SELECT emp_no | '-' | dept_no AS emp_dept
FROM emp_dept_mapping;

Oracle 스타일로 변환:

-- Oracle 표준 방식 1: || 연산자 사용
SELECT emp_no || '-' || dept_no AS emp_dept
FROM emp_dept_mapping;

-- Oracle 표준 방식 2: CONCAT 함수 사용 (두 개 인수만 지원)
SELECT CONCAT(CONCAT(emp_no, '-'), dept_no) AS emp_dept
FROM emp_dept_mapping;

-- 실용적인 예시: 주소 조합
SELECT street_address || ', ' || city || ', ' || state_province AS full_address
FROM locations
WHERE country_id = 'US';

원인 3: 동적 SQL 수정

PL/SQL 동적 SQL에서의 잘못된 예:

-- 잘못된 동적 SQL 조합 (ORA-00996 유발 가능)
DECLARE
    v_sql VARCHAR2(1000);
    v_operator VARCHAR2(5) := '|';  -- 잘못된 연산자 변수
BEGIN
    v_sql := 'SELECT first_name ' || v_operator || ' last_name FROM employees';
    EXECUTE IMMEDIATE v_sql;
END;
/

올바른 동적 SQL:

-- 올바른 동적 SQL 조합
DECLARE
    v_sql       VARCHAR2(1000);
    v_result    SYS_REFCURSOR;
    v_full_name VARCHAR2(100);
BEGIN
    -- 연산자를 올바르게 이중 파이프로 지정
    v_sql := 'SELECT first_name || '' '' || last_name AS full_name '
          || 'FROM employees '
          || 'WHERE department_id = :dept_id';

    OPEN v_result FOR v_sql USING 10;

    LOOP
        FETCH v_result INTO v_full_name;
        EXIT WHEN v_result%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_full_name);
    END LOOP;

    CLOSE v_result;
END;
/

실무에서 자주 쓰는 문자열 연결 패턴:

-- NULL 처리를 포함한 안전한 문자열 연결
SELECT NVL(first_name, '') || ' ' || NVL(last_name, 'Unknown') AS safe_full_name
FROM employees;

-- TO_CHAR를 활용한 숫자/날짜 연결
SELECT employee_id || ' - ' || first_name || ' (입사일: '
       || TO_CHAR(hire_date, 'YYYY-MM-DD') || ')' AS emp_info
FROM employees
WHERE department_id = 20;

-- CASE 표현식과 함께 사용
SELECT first_name || ' ' || last_name
       || CASE WHEN salary > 10000 THEN ' [고연봉]' ELSE '' END AS emp_label
FROM employees;

예방 방법

  • 코딩 컨벤션 문서화 및 코드 리뷰 프로세스 도입

팀 내 Oracle SQL 코딩 가이드라인 문서에 “문자열 연결은 반드시 || 사용”을 명시하고, 모든 SQL/PL/SQL 코드는 배포 전 반드시 동료 리뷰를 거치도록 프로세스를 수립하세요. IDE(SQL Developer, Toad, DBeaver 등)의 문법 강조(Syntax Highlighting) 기능을 활성화하면 단일 |와 이중 ||의 색상 차이로 시각적으로 오류를 사전에 확인할 수 있습니다. 또한 CI/CD 파이프라인에 SQL 린터(SQLFluff 등)를 통합하여 자동으로 문법 오류를 검출하는 체계를 구축하면 운영 환경 배포 전에 대부분의 문법 오류를 잡아낼 수 있습니다.

  • Oracle SQL 문법 교육 및 마이그레이션 체크리스트 활용

신규 입사자나 타 DBMS 경험자를 대상으로 Oracle 고유 문법(연산자, 함수 등)에 대한 온보딩 교육을 정기적으로 실시하고, 특히 || 연산자의 올바른 사용법을 강조하세요. 타 DBMS에서 Oracle로 코드를 마이그레이션할 때는 문자열 연결 연산자 변환 항목이 포함된 체크리스트를 반드시 사용하고, 마이그레이션 완료 후 단위 테스트를 통해 모든 SQL 문의 정상 동작 여부를 검증하는 절차를 표준화하세요.


관련 에러

  • ORA-00907: missing right parenthesis — 괄호 누락으로 발생하는 문법 에러로, ORA-00996과 함께 SQL 문법 오류 계열에 속합니다.
  • ORA-00917: missing comma — 컬럼 목록이나 값 목록에서 쉼표 누락 시 발생하며, 마찬가지로 SQL 파싱 단계에서 감지됩니다.
  • ORA-00920: invalid relational operator — 잘못된 비교 연산자 사용 시 발생하는 에러로, 연산자 오용 계열의 에러입니다.
  • ORA-00923: FROM keyword not found where expected — SELECT 문의 구조적 문법 오류로, 잘못된 연산자 사용이 후속 키워드 인식 실패로 이어질 때 함께 발생할 수 있습니다.
  • ORA-06550: PL/SQL 블록 내에서 위와 같은 문법 오류가 발생할 때 PL/SQL 컴파일 에러 래퍼로 함께 출력되는 에러 코드입니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기