ORA-00900 : SQL 문이 부적합합니다 - 원인과 해결법 완벽 가이드
오라클 데이터베이스를 사용하다 보면 가장 먼저 만나는 에러 중 하나가 바로 ORA-00900: invalid SQL statement입니다. 이 에러는 오라클이 입력된 SQL 문장 자체를 인식하지 못할 때 발생합니다. 이번 글에서는 ORA-00900 에러의 모든 원인과 해결법을 실전 예제와 함께 정리합니다.

ORA-00900 에러란?
ORA-00900은 오라클 SQL 파서가 입력된 SQL 문장을 유효한 SQL로 인식하지 못할 때 발생하는 에러입니다.

공식 메시지는 다음과 같습니다.
ORA-00900: invalid SQL statement
(SQL 문이 부적합합니다)
오라클은 SQL 문장을 파싱하는 과정에서 문법적으로 유효하지 않다고 판단하면 이 에러를 반환합니다. 즉, SELECT, INSERT, UPDATE, DELETE 등 유효한 SQL 명령어로 시작하지 않거나, SQL 문법 자체가 근본적으로 잘못된 경우에 발생합니다.
주요 발생 원인 6가지
ORA-00900이 발생하는 대표적인 원인을 정리하면 다음과 같습니다.

| 번호 | 원인 | 설명 |
|---|---|---|
| 1 | SQL 키워드 오타 | SELCET, UDPATE 등 명령어 철자 오류 |
| 2 | 빈 SQL 문 실행 | 아무 내용 없이 실행 버튼을 누른 경우 |
| 3 | PL/SQL을 SQL로 실행 | BEGIN-END 블록을 SQL 창에서 실행 |
| 4 | 지원하지 않는 문법 | 다른 DBMS 문법을 오라클에서 사용 |
| 5 | 주석만 있는 SQL | 주석만 남기고 실제 SQL은 없는 경우 |
| 6 | 특수문자/인코딩 오류 | 보이지 않는 특수문자가 포함된 경우 |
원인 1: SQL 키워드 오타
가장 흔한 원인입니다. SQL 명령어의 철자가 틀리면 오라클이 해당 문장을 SQL로 인식하지 못합니다.

에러 발생 예시:
-- SELCET 오타
SELCET * FROM employees;
-- UDPATE 오타
UDPATE employees SET salary = 5000 WHERE employee_id = 100;
-- DELTE 오타
DELTE FROM employees WHERE employee_id = 100;
해결법:
-- 올바른 키워드 사용
SELECT * FROM employees;
UPDATE employees SET salary = 5000 WHERE employee_id = 100;
DELETE FROM employees WHERE employee_id = 100;
SQL 키워드를 정확하게 입력했는지 확인하세요. IDE의 자동완성 기능을 활용하면 오타를 줄일 수 있습니다.
원인 2: 빈 SQL 문 실행
SQL Developer나 Toad 같은 도구에서 아무 내용 없이 실행 버튼을 누르거나, 변수에 빈 문자열을 넣어 실행하는 경우 발생합니다.

에러 발생 예시:
-- SQL Developer에서 빈 영역 선택 후 실행
-- (아무것도 입력하지 않은 상태)
-- PL/SQL에서 빈 변수로 EXECUTE IMMEDIATE 실행
DECLARE
v_sql VARCHAR2(1000) := '';
BEGIN
EXECUTE IMMEDIATE v_sql; -- ORA-00900 발생!
END;
/
해결법:
-- EXECUTE IMMEDIATE 사용 시 NULL/빈 문자열 체크
DECLARE
v_sql VARCHAR2(1000) := '';
BEGIN
IF v_sql IS NOT NULL AND LENGTH(TRIM(v_sql)) > 0 THEN
EXECUTE IMMEDIATE v_sql;
ELSE
DBMS_OUTPUT.PUT_LINE('SQL 문이 비어 있습니다.');
END IF;
END;
/
동적 SQL을 사용할 때는 반드시 SQL 문자열이 비어 있지 않은지 사전에 검증해야 합니다.
원인 3: PL/SQL을 SQL 창에서 실행
PL/SQL 블록(BEGIN-END)을 SQL 실행 창에서 그대로 실행하면 ORA-00900이 발생할 수 있습니다. 특히 SQL*Plus가 아닌 환경에서 자주 발생합니다.

에러 발생 예시:
-- SQL 실행 모드에서 PL/SQL 블록 실행 시
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello');
END;
해결법:
-- 방법 1: 끝에 슬래시(/) 추가 (SQL*Plus, SQL Developer)
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello');
END;
/
-- 방법 2: SQL Developer에서 "스크립트 실행(F5)" 사용
-- (일반 실행 Ctrl+Enter 대신 F5 키)
SQL Developer에서는 PL/SQL 블록 실행 시 F5(스크립트 실행)을 사용하거나, 블록 끝에 슬래시(/)를 반드시 추가해야 합니다.
원인 4: 다른 DBMS 문법 사용
MySQL, SQL Server 등 다른 데이터베이스의 문법을 오라클에서 그대로 사용하면 ORA-00900이 발생합니다.

에러 발생 예시:
-- MySQL 문법: LIMIT (오라클에서 지원하지 않음)
SELECT * FROM employees LIMIT 10;
-- SQL Server 문법: TOP
SELECT TOP 10 * FROM employees;
-- MySQL 문법: SHOW TABLES
SHOW TABLES;
-- MySQL 문법: USE database
USE hr;
해결법:
-- 오라클에서 행 수 제한: ROWNUM 또는 FETCH FIRST (12c 이상)
SELECT * FROM employees WHERE ROWNUM <= 10;
-- 12c 이상
SELECT * FROM employees FETCH FIRST 10 ROWS ONLY;
-- 테이블 목록 조회
SELECT table_name FROM user_tables;
-- 스키마 변경
ALTER SESSION SET CURRENT_SCHEMA = hr;
| MySQL / SQL Server | Oracle 대체 문법 |
|---|---|
| LIMIT 10 | WHERE ROWNUM <= 10 또는 FETCH FIRST 10 ROWS ONLY |
| TOP 10 | WHERE ROWNUM <= 10 |
| SHOW TABLES | SELECT table_name FROM user_tables |
| USE database | ALTER SESSION SET CURRENT_SCHEMA = 스키마명 |
| IFNULL() | NVL() |
| NOW() | SYSDATE |
원인 5: 주석만 있는 SQL
SQL 문 전체가 주석으로 처리되어 실제 실행할 SQL이 없는 경우에도 발생합니다.

에러 발생 예시:
-- 전체가 주석 처리됨
-- SELECT * FROM employees;
/*
SELECT * FROM employees
WHERE department_id = 10;
*/
해결법:
주석을 제거하고 실제 SQL 문을 활성화하세요.
-- 아래 쿼리를 실행합니다
SELECT * FROM employees
WHERE department_id = 10;
특히 디버깅 중 SQL을 주석 처리했다가 해제하지 않고 실행하는 실수가 많습니다. 실행 전에 활성화된 SQL이 있는지 반드시 확인하세요.
원인 6: 보이지 않는 특수문자
웹 페이지나 문서에서 SQL을 복사-붙여넣기 할 때 보이지 않는 특수문자(Zero-Width Space, BOM 등)가 포함되어 발생합니다.

에러 발생 상황:
- 웹 블로그에서 SQL 복사 후 붙여넣기
- Word, PDF 문서에서 SQL 복사
- 카카오톡, 슬랙 등 메신저에서 SQL 복사
해결법:
-- 방법 1: 메모장(Notepad)에 먼저 붙여넣기 후 다시 복사
-- (서식 없는 텍스트로 변환됨)
-- 방법 2: SQL Developer에서 새 워크시트에 직접 타이핑
-- 방법 3: Notepad++에서 특수문자 표시 기능으로 확인
-- 메뉴 > 보기 > 특수 문자 표시 > 모든 문자 표시
의심이 되면 SQL을 처음부터 직접 타이핑하는 것이 가장 확실한 해결법입니다.
EXECUTE IMMEDIATE에서 ORA-00900 방지하기
동적 SQL을 사용하는 PL/SQL 프로그램에서 ORA-00900은 특히 자주 발생합니다. 안전한 동적 SQL 실행 패턴을 소개합니다.

안전한 동적 SQL 패턴:
CREATE OR REPLACE PROCEDURE exec_dynamic_sql(p_sql IN VARCHAR2) IS
BEGIN
-- 1. NULL/빈 문자열 체크
IF p_sql IS NULL OR LENGTH(TRIM(p_sql)) = 0 THEN
RAISE_APPLICATION_ERROR(-20001, 'SQL 문이 비어 있습니다.');
END IF;
-- 2. 유효한 SQL 키워드로 시작하는지 체크
IF NOT REGEXP_LIKE(UPPER(TRIM(p_sql)),
'^(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|MERGE|GRANT|REVOKE)')
THEN
RAISE_APPLICATION_ERROR(-20002, '유효하지 않은 SQL 문입니다.');
END IF;
-- 3. 실행
EXECUTE IMMEDIATE p_sql;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQL 실행 에러: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('문제 SQL: ' || SUBSTR(p_sql, 1, 200));
RAISE;
END;
/
| 체크 항목 | 방법 | 목적 |
|---|---|---|
| NULL 체크 | IS NULL 확인 | 빈 SQL 방지 |
| 공백 체크 | LENGTH(TRIM()) | 공백만 있는 SQL 방지 |
| 키워드 체크 | REGEXP_LIKE | 유효하지 않은 명령어 방지 |
| 예외 처리 | EXCEPTION | 에러 발생 시 원인 로깅 |
자주 묻는 질문 (FAQ)
Q1. ORA-00900과 ORA-00933의 차이점은 무엇인가요?
ORA-00900은 SQL 문장 자체를 인식할 수 없는 경우(명령어 오류, 빈 SQL 등)에 발생하고, ORA-00933은 SQL 문법이 올바르게 종료되지 않은 경우에 발생합니다. 예를 들어 SELCET * FROM emp는 ORA-00900, SELECT * FROM emp ORDER BY 1 LIMIT 10은 ORA-00933입니다.
Q2. SQL Developer에서만 ORA-00900이 발생하고 SQL*Plus에서는 안 나요.
PL/SQL 블록 실행 방식의 차이일 수 있습니다. SQL Developer에서는 F5(스크립트 실행)로 실행하거나, PL/SQL 블록 끝에 슬래시(/)를 추가해 보세요.
Q3. EXECUTE IMMEDIATE 사용 시 자꾸 ORA-00900이 발생합니다.
동적 SQL 변수의 값을 DBMS_OUTPUT.PUT_LINE으로 출력해서 실제 SQL 내용을 확인하세요. 빈 문자열이거나 잘못된 SQL이 들어가는 경우가 대부분입니다.
Q4. 복사-붙여넣기한 SQL에서 ORA-00900이 발생하는데 문법이 맞아 보입니다.
보이지 않는 특수문자가 포함되었을 가능성이 높습니다. 메모장에 먼저 붙여넣기한 뒤 다시 복사하거나, SQL을 직접 새로 타이핑해 보세요.
핵심 정리
ORA-00900 에러는 SQL 문장 자체가 유효하지 않을 때 발생하는 기본적인 에러입니다. 대부분 키워드 오타, 빈 SQL 실행, 다른 DBMS 문법 사용 등 단순한 원인에서 비롯됩니다.
| 점검 사항 | 확인 방법 |
|---|---|
| SQL 키워드 철자 확인 | SELECT, INSERT, UPDATE, DELETE 등 정확히 입력 |
| 빈 SQL 여부 확인 | EXECUTE IMMEDIATE 사용 시 NULL 체크 |
| PL/SQL 실행 방식 확인 | F5 또는 슬래시(/) 사용 |
| DBMS 문법 호환성 확인 | MySQL/SQL Server 문법을 Oracle 문법으로 변환 |
| 특수문자 여부 확인 | 메모장에 붙여넣기 후 재복사 |
태그: ORA-00900, ORA-00900 해결, ORA-00900 원인, oracle error, 오라클 에러, SQL 문이 부적합합니다, invalid SQL statement, 오라클 에러 해결, EXECUTE IMMEDIATE 에러, 오라클 SQL 오류, 오라클 구문 에러, 오라클 입문, SQL Developer 에러, 오라클 트러블슈팅, 데이터베이스 에러
'IT' 카테고리의 다른 글
| ORA-00904 : 부적합한 식별자, 이것만 확인하면 해결 (0) | 2026.04.08 |
|---|---|
| ORA-00903 : 테이블명이 부적합합니다 - 예약어부터 명명규칙까지 (0) | 2026.04.08 |
| Claude Code 꿀팁 총정리: 생산성 200% 올리는 숨은 기능 모음 (1) | 2026.03.12 |
| Claude Code 디버깅 완전정리: 버그 잡는 AI 에이전트의 모든 것 (0) | 2026.03.12 |
| Claude Code 리팩토링 완전정리: 코드 구조 개선의 모든 것 (0) | 2026.03.12 |
댓글