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

ORA-01036
2026년 06월 30일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-01036 illegal variable name/number 는?

ORA-01036 에러는 Oracle 데이터베이스에서 바인드 변수(Bind Variable)를 사용할 때 변수 이름이나 번호가 잘못 지정되었을 때 발생하는 에러입니다. 주로 애플리케이션 코드에서 SQL 쿼리에 바인드 변수를 전달하는 과정에서 변수명이 일치하지 않거나, 존재하지 않는 변수를 참조할 때 Oracle 엔진이 이를 인식하지 못해 발생합니다. 이 에러는 Java(JDBC), Python(cx_Oracle), .NET(ODP.NET), Pro*C 등 다양한 언어와 프레임워크에서 Oracle과 연동할 때 자주 목격되며, 개발 초보자뿐 아니라 숙련된 개발자도 종종 실수하는 에러 중 하나입니다.


주요 발생 원인

1. 바인드 변수명 불일치 또는 잘못된 변수명 사용

가장 흔한 원인으로, SQL 쿼리 내에서 선언한 바인드 변수 이름과 애플리케이션 코드에서 실제로 바인딩하는 변수 이름이 서로 다를 때 발생합니다. 예를 들어, 쿼리에는 :emp_id라고 선언했지만 코드에서는 :empid 혹은 :EMP_ID처럼 대소문자나 언더스코어 유무가 다르게 입력한 경우가 대표적입니다. Oracle은 바인드 변수명에 대해 대소문자를 구분하지 않지만, 일부 드라이버나 ORM 프레임워크는 내부적으로 변수명을 변환하여 불일치를 일으킬 수 있습니다.

2. 바인드 변수 개수 및 순서 불일치

위치 기반(Positional) 바인드 방식을 사용하는 환경(예: ODP.NET의 일부 설정, Pro*C 등)에서 SQL 쿼리에 선언된 바인드 변수의 개수와 코드에서 실제로 추가한 파라미터의 개수가 맞지 않을 때 발생합니다. 특히 쿼리를 동적으로 생성하는 로직에서 조건절이 추가되거나 삭제될 때, 파라미터 바인딩 코드를 함께 수정하지 않으면 이 에러가 발생하기 쉽습니다. 순서가 뒤바뀐 경우에도 ORA-01036이 발생하거나, 더 심각한 경우 데이터 오염이 발생할 수 있어 각별한 주의가 필요합니다.

3. 잘못된 바인드 변수 문법 또는 특수문자 포함

바인드 변수 이름에 허용되지 않는 특수문자(예: -, @, # 일부 상황 등)가 포함되거나, 콜론(:) 없이 변수를 선언한 경우에도 이 에러가 발생합니다. 또한 동적 SQL을 구성하는 과정에서 문자열 결합 오류로 인해 :변수명 앞뒤에 공백이나 불필요한 문자가 삽입되는 경우도 원인이 됩니다. PL/SQL 블록 내에서 EXECUTE IMMEDIATE와 함께 USING 절을 잘못 작성한 경우도 동일한 에러를 유발할 수 있습니다.


해결 방법

원인 1 해결: 바인드 변수명 일치 확인

SQL 쿼리와 애플리케이션 코드 양쪽에서 변수명이 동일한지 꼼꼼히 확인합니다.

잘못된 예시 (Java JDBC):

-- SQL 쿼리의 바인드 변수명: emp_id
String sql = "SELECT * FROM employees WHERE employee_id = :emp_id";

-- 하지만 코드에서는 다른 이름으로 바인딩 시도
OraclePreparedStatement pstmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pstmt.setIntAtName("empid", 100);  -- 오류: emp_id 와 empid 불일치

올바른 예시 (Java JDBC):

String sql = "SELECT * FROM employees WHERE employee_id = :emp_id";
OraclePreparedStatement pstmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pstmt.setIntAtName("emp_id", 100);  -- 정확히 일치하는 변수명 사용
pstmt.execute();

PL/SQL에서 올바른 바인드 변수 사용 예시:

DECLARE
  v_emp_id   employees.employee_id%TYPE := 100;
  v_emp_name employees.last_name%TYPE;
BEGIN
  -- EXECUTE IMMEDIATE + USING 절 올바른 사용
  EXECUTE IMMEDIATE
    'SELECT last_name FROM employees WHERE employee_id = :emp_id'
  INTO v_emp_name
  USING v_emp_id;

  DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_emp_name);
END;
/

원인 2 해결: 바인드 변수 개수 및 순서 맞추기

동적 SQL 생성 시 파라미터 개수와 바인드 변수 개수를 반드시 동기화합니다.

잘못된 예시 (동적 쿼리에서 파라미터 누락):

-- WHERE 절에 바인드 변수가 2개인데 USING에 1개만 전달
DECLARE
  v_sql    VARCHAR2(500);
  v_result VARCHAR2(100);
BEGIN
  v_sql := 'SELECT last_name FROM employees 
             WHERE department_id = :dept_id 
               AND job_id = :job_id';

  -- 오류: USING 절에 :job_id에 해당하는 값이 없음
  EXECUTE IMMEDIATE v_sql INTO v_result USING 90;
END;
/

올바른 예시:

DECLARE
  v_sql    VARCHAR2(500);
  v_result VARCHAR2(100);
BEGIN
  v_sql := 'SELECT last_name FROM employees 
             WHERE department_id = :dept_id 
               AND job_id = :job_id';

  -- 바인드 변수 순서와 개수를 맞춰 전달
  EXECUTE IMMEDIATE v_sql INTO v_result USING 90, 'AD_VP';
  DBMS_OUTPUT.PUT_LINE('Result: ' || v_result);
END;
/

위치 기반 바인드 변수 개수 검증 예시 (Python cx_Oracle):

import cx_Oracle

conn = cx_Oracle.connect("user/password@dsn")
cursor = conn.cursor()

# 쿼리에 바인드 변수 2개 선언
sql = """
    SELECT employee_id, last_name, salary
    FROM employees
    WHERE department_id = :dept_id
      AND salary > :min_salary
"""

# 반드시 동일한 개수의 파라미터 전달
cursor.execute(sql, dept_id=90, min_salary=5000)
rows = cursor.fetchall()
for row in rows:
    print(row)

원인 3 해결: 바인드 변수 문법 교정

바인드 변수명에 허용되지 않는 문자가 포함되지 않았는지 확인하고, 동적 SQL 문자열 결합 시 주의합니다.

잘못된 예시 (특수문자 포함 및 공백 오류):

DECLARE
  v_sql    VARCHAR2(500);
  v_result NUMBER;
BEGIN
  -- 오류 1: 바인드 변수명에 하이픈(-) 사용 불가
  v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = :dept-id';

  -- 오류 2: 문자열 결합 실수로 ': dept_id'처럼 공백 삽입
  v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = : dept_id';

  EXECUTE IMMEDIATE v_sql INTO v_result USING 90;
END;
/

올바른 예시:

DECLARE
  v_sql    VARCHAR2(500);
  v_result NUMBER;
BEGIN
  -- 올바른 바인드 변수명: 알파벳, 숫자, 언더스코어만 사용
  v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = :dept_id';

  EXECUTE IMMEDIATE v_sql INTO v_result USING 90;
  DBMS_OUTPUT.PUT_LINE('Count: ' || v_result);
END;
/

복수 바인드 변수 재사용 주의 (동일 변수명을 여러 번 사용하는 경우):

DECLARE
  v_sql    VARCHAR2(500);
  v_result NUMBER;
  v_dept   NUMBER := 90;
BEGIN
  -- 동일한 바인드 변수 :dept_id 를 두 번 사용하는 경우
  -- EXECUTE IMMEDIATE USING 절에서는 사용된 횟수만큼 값을 전달해야 함
  v_sql := 'SELECT COUNT(*) FROM employees 
             WHERE department_id = :dept_id 
                OR manager_id IN (
                   SELECT employee_id FROM employees 
                   WHERE department_id = :dept_id
                )';

  -- :dept_id 가 2번 등장하므로 USING에도 2번 전달
  EXECUTE IMMEDIATE v_sql INTO v_result USING v_dept, v_dept;
  DBMS_OUTPUT.PUT_LINE('Count: ' || v_result);
END;
/

예방 방법

1. 바인드 변수 명명 규칙(Naming Convention) 표준화 및 코드 리뷰

팀 내에서 바인드 변수 명명 규칙을 표준화하고, SQL 쿼리와 바인딩 코드를 함께 리뷰하는 프로세스를 도입하세요. 예를 들어 :p_컬럼명 형식으로 통일하거나, 입력 파라미터는 :in_변수명, 출력 파라미터는 :out_변수명 형식으로 구분하는 것이 좋습니다. 동적 SQL을 생성하는 함수나 프로시저에는 반드시 단위 테스트(Unit Test)를 작성하여 바인드 변수 개수와 파라미터 개수가 항상 일치하는지 자동으로 검증하는 체계를 갖추는 것을 권장합니다.

2. ORM 또는 쿼리 빌더 사용 및 드라이버 버전 관리

MyBatis, Hibernate, SQLAlchemy 등 검증된 ORM 프레임워크나 쿼리 빌더를 사용하면 바인드 변수 처리를 프레임워크가 대신해주므로 ORA-01036 발생 가능성을 크게 줄일 수 있습니다. 직접 JDBC, cx_Oracle, ODP.NET 등의 드라이버를 사용하는 경우에는 드라이버 버전을 최신으로 유지하고, 각 드라이버의 바인드 변수 처리 방식(Named Binding vs Positional Binding)을 정확히 이해하고 사용해야 합니다. 특히 팀원들이 서로 다른 드라이버 버전을 사용하면 동작 방식의 차이로 인한 에러가 발생할 수 있으므로, 의존성 버전을 프로젝트 차원에서 고정하여 관리하는 것이 중요합니다.


관련 에러

  • ORA-01008: not all variables bound – SQL 쿼리 내 바인드 변수 중 일부가 바인딩되지 않았을 때 발생하며, ORA-01036과 유사한 상황에서 함께 나타나는 경우가 많습니다.
  • ORA-00904: invalid identifier – 바인드 변수가 아닌 컬럼명이나 객체명이 잘못 지정된 경우 발생하며, 동적 SQL 작성 시 ORA-01036과 혼동하기 쉽습니다.
  • ORA-06512: at line N – PL/SQL 블록 내에서 ORA-01036이 발생할 때 함께 출력되어 에러가 발생한 정확한 라인을 알려주는 보조 에러 메시지입니다.
  • ORA-01722: invalid number – 바인드 변수에 잘못된 타입의 값을 전달했을 때 발생하며, 바인드 변수 관련 에러 디버깅 시 함께 확인해야 할 에러입니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기