[오라클 에러] ORA-00942 table or view does not exist - 6가지 원인과 해결방법 (권한과 PL/SQL 케이스까지)
테스트 환경: Oracle 11g / 12c / 19c / 21c
ORA-00942는 오라클에서 가장 자주 마주치는 에러 중 하나입니다. 메시지가 단순해서 "그 객체가 없나 보다" 하고 넘기기 쉽지만, 실제로는 객체가 존재하는데도 ORA-00942가 나는 케이스가 절반 이상입니다.
특히 다음 상황에서 자주 발생합니다.
- 분명히 테이블이 있는데 SELECT가 안 됨
- 다른 사용자는 되는데 내 계정만 안 됨
- 어제까지 잘 되던 프로시저가 갑자기 ORA-00942
- 쿼리는 잘 되는데 PL/SQL 안에서만 ORA-00942
이 글에서는 ORA-00942의 6가지 원인을 분류하고, 권한 부족인데 왜 ORA-01031이 아니라 ORA-00942가 나는지, 그리고 PL/SQL 내부에서의 특수한 케이스까지 정리했습니다.
급하신 분은 빠른 진단 체크리스트부터 보세요.
에러 메시지 전문
ORA-00942: table or view does not exist
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다
SQL*Plus, SQL Developer, JDBC, 애플리케이션 로그 어디에서나 동일하게 발생합니다. 에러 메시지가 어떤 객체인지 알려주지 않는 게 진단을 어렵게 만드는 부분입니다.
중요: 메시지가 "존재하지 않는다"고 말하지만, 오라클은 "보이지 않는다"와 "존재하지 않는다"를 같은 에러로 처리합니다. 이게 ORA-00942의 진짜 정체입니다.
ORA-00942의 핵심 개념 - 권한과 가시성
다른 블로그에서 잘 다루지 않는 부분이지만, 이걸 이해해야 ORA-00942를 진짜로 해결할 수 있습니다.
왜 권한 부족이 ORA-01031이 아니라 ORA-00942인가
오라클의 보안 설계는 "권한 없는 사용자에게는 객체의 존재 자체를 알리지 않는다" 는 원칙을 따릅니다.
만약 권한 부족 시 ORA-01031("권한이 불충분합니다")이 발생한다면, 공격자는 다음을 알 수 있습니다.
- ORA-00942 응답 → 그런 객체 없음
- ORA-01031 응답 → 객체는 있는데 권한 없음 (= 객체가 존재한다는 정보 노출)
이건 데이터베이스 구조 정보를 노출하는 보안 취약점입니다. 그래서 오라클은 권한이 없으면 "존재하지 않음"이라고 응답합니다. 즉:
ORA-00942는 "객체가 없다"가 아니라, "당신에게는 보이지 않는다"는 의미입니다.
이 차이를 알면 진단 방향이 완전히 달라집니다.
빠른 진단 체크리스트
ORA-00942를 30초 만에 원인을 좁히는 순서입니다.
- DBA 계정으로 객체 존재 여부 확인 → 정말 없는가, 아니면 보이지 않는가?
- 객체의 소유 스키마 확인 → 다른 스키마인가?
- 현재 사용자에게 SELECT 권한이 있는가
- PL/SQL 안에서 발생했는가 → ROLE 권한 문제일 가능성
- 객체가 INVALID 상태인가 → 의존성 깨진 뷰/시노님
- 객체 이름에 대소문자/특수문자 포함? → 따옴표 케이스
원인 1: 객체가 실제로 없거나 오타 (가장 흔함)
기본적인 케이스지만 가장 많이 발생합니다.
진단 방법
DBA 권한으로 객체가 실제로 존재하는지 확인:
-- 모든 스키마에서 해당 객체 검색
SELECT owner, object_name, object_type, status
FROM dba_objects
WHERE UPPER(object_name) = UPPER('찾는_객체명');
행이 0건이면 객체가 정말 없는 것입니다. 행이 있다면 다음 원인으로 넘어가세요.
해결 방법
- 객체명 오타 수정
- 객체 생성 (필요한 경우)
- 다른 환경(개발/스테이징)에 있는지 확인
원인 2: 다른 스키마의 객체에 접근 (스키마 prefix 누락) ★ 가장 자주 헷갈림
오라클에서 객체는 항상 소유 스키마에 속합니다. 다른 스키마의 객체에 접근할 때는 스키마명을 명시해야 합니다.
시나리오
-- APP_USER 스키마에 EMPLOYEES 테이블이 있고
-- 현재 접속한 사용자는 BATCH_USER일 때
SELECT * FROM employees; -- ❌ ORA-00942
SELECT * FROM app_user.employees; -- ✅ 가능 (권한이 있다면)
진단 방법
-- 객체가 어느 스키마에 있는지 확인
SELECT owner, object_name, object_type
FROM all_objects
WHERE UPPER(object_name) = UPPER('EMPLOYEES');
owner 컬럼이 현재 접속 사용자(USER)와 다르면 prefix가 필요합니다.
해결 방법
방법 1: 스키마 prefix 추가
SELECT * FROM app_user.employees;
방법 2: 시노님(SYNONYM) 생성 (권장)
-- PUBLIC 시노님 (모든 사용자가 prefix 없이 접근)
CREATE PUBLIC SYNONYM employees FOR app_user.employees;
-- PRIVATE 시노님 (특정 사용자만)
CREATE SYNONYM employees FOR app_user.employees;
방법 3: 권한 부여 + 시노님 조합 (실무 표준)
-- APP_USER로 접속해서
GRANT SELECT ON employees TO batch_user;
-- BATCH_USER로 접속해서
CREATE SYNONYM employees FOR app_user.employees;
이렇게 하면 BATCH_USER가 SELECT * FROM employees로 접근 가능합니다.
원인 3: 권한 부족 (객체는 있지만 보이지 않음)
원인 2와 비슷해 보이지만, 권한 자체가 없는 경우입니다.
진단 방법
현재 사용자가 해당 객체에 어떤 권한이 있는지 확인합니다.
-- 직접 부여받은 권한
SELECT * FROM user_tab_privs
WHERE table_name = 'EMPLOYEES';
-- ROLE을 통해 받은 권한
SELECT role, table_name, privilege
FROM role_tab_privs
WHERE role IN (SELECT granted_role FROM user_role_privs)
AND table_name = 'EMPLOYEES';
두 쿼리 모두 결과가 없으면 권한이 전혀 없는 것입니다.
해결 방법
객체 소유자(또는 DBA)가 권한을 부여합니다.
-- 객체 소유자로 접속
GRANT SELECT ON employees TO batch_user;
-- 여러 권한 한 번에
GRANT SELECT, INSERT, UPDATE, DELETE ON employees TO batch_user;
-- 모든 권한
GRANT ALL ON employees TO batch_user;
권한 부여 후 클라이언트는 재접속해야 즉시 반영됩니다(세션 캐시 때문).
실무 팁
운영 환경에서는 개별 사용자에게 직접 권한을 주지 말고 ROLE 기반으로 관리하세요.
-- ROLE 생성
CREATE ROLE ROLE_BATCH_READ;
-- ROLE에 권한 부여
GRANT SELECT ON app_user.employees TO ROLE_BATCH_READ;
GRANT SELECT ON app_user.departments TO ROLE_BATCH_READ;
-- 사용자에게 ROLE 부여
GRANT ROLE_BATCH_READ TO batch_user;
다만 ROLE 기반 권한에는 PL/SQL에서의 함정이 있습니다(다음 원인 4 참고).
원인 4: PL/SQL 내부에서 ORA-00942 (★ 고급, 가장 까다로움)
이 케이스는 다른 블로그에서 거의 다루지 않는 영역인데, PL/SQL 개발자가 만나면 가장 헷갈리는 케이스입니다.
증상
- 직접 SQL로는 SELECT * FROM employees 가 잘 됨
- 똑같은 SQL을 PL/SQL 프로시저 안에 넣으면 ORA-00942
- 어제까지 잘 되던 프로시저가 갑자기 컴파일 안 됨
원인: DEFINER vs INVOKER 권한 + ROLE 무효화
오라클 PL/SQL은 기본적으로 DEFINER rights(정의자 권한) 으로 동작합니다. 즉:
- 프로시저를 만든 사용자(소유자) 의 권한으로 실행
- 호출하는 사용자의 권한이 아님
그리고 결정적으로, DEFINER rights PL/SQL에서는 ROLE을 통해 받은 권한이 무효화됩니다.
예시 시나리오
-- 1) APP_USER가 EMPLOYEES 테이블 소유
-- 2) BATCH_USER에게 ROLE 통해 권한 부여
GRANT SELECT ON app_user.employees TO ROLE_BATCH_READ;
GRANT ROLE_BATCH_READ TO batch_user;
-- 3) BATCH_USER로 접속해서 직접 SQL 실행
SELECT * FROM app_user.employees;
-- ✅ 잘 됨 (ROLE 권한 인식)
-- 4) 같은 SQL을 BATCH_USER 소유 프로시저에 넣음
CREATE OR REPLACE PROCEDURE PROC_READ_EMP AS
CURSOR c1 IS SELECT * FROM app_user.employees;
BEGIN
NULL;
END;
/
-- ❌ ORA-00942 발생 (ROLE 권한 무효화)
해결 방법
방법 1: 직접 GRANT (가장 흔한 해결)
-- ROLE을 거치지 말고 직접 부여
GRANT SELECT ON app_user.employees TO batch_user;
이후 프로시저 재컴파일:
ALTER PROCEDURE PROC_READ_EMP COMPILE;
방법 2: INVOKER rights로 변경
CREATE OR REPLACE PROCEDURE PROC_READ_EMP
AUTHID CURRENT_USER -- ← INVOKER rights
AS
CURSOR c1 IS SELECT * FROM app_user.employees;
BEGIN
NULL;
END;
/
AUTHID CURRENT_USER를 명시하면 호출한 사용자의 권한으로 실행되어 ROLE 권한도 인식됩니다. 다만 운영 환경에서는 보안 정책에 따라 신중히 결정해야 합니다.
실무 팁
운영 환경에서 갑자기 프로시저가 ORA-00942로 동작 안 한다면 다음을 의심하세요.
- 객체 소유자 또는 권한 부여가 변경됨
- ROLE에서 권한이 회수됨
- 참조하는 객체가 다른 스키마로 이동
dba_dependencies 뷰로 프로시저가 어떤 객체를 참조하는지 확인할 수 있습니다.
SELECT referenced_owner, referenced_name, referenced_type
FROM dba_dependencies
WHERE owner = 'BATCH_USER'
AND name = 'PROC_READ_EMP';
원인 5: 시노님이 깨졌거나 가리키는 객체가 없음
시노님은 다른 객체를 가리키는 별칭일 뿐, 시노님 자체가 객체를 보장하지 않습니다. 원본 객체가 사라지거나 권한이 회수되면 시노님은 살아있지만 사용 시 ORA-00942 가 발생합니다.
진단 방법
-- 시노님이 가리키는 대상 확인
SELECT owner, synonym_name, table_owner, table_name
FROM all_synonyms
WHERE UPPER(synonym_name) = UPPER('찾는_객체명');
가리키는 table_owner.table_name이 실제로 존재하는지 별도로 확인:
SELECT owner, object_name, object_type, status
FROM dba_objects
WHERE owner = '확인된_OWNER'
AND object_name = '확인된_NAME';
원본 객체가 없거나 권한이 없으면 시노님이 깨진 것입니다.
해결 방법
-- 깨진 시노님 제거 후 재생성
DROP PUBLIC SYNONYM employees;
CREATE PUBLIC SYNONYM employees FOR app_user.employees;
-- 또는 권한 재부여
GRANT SELECT ON app_user.employees TO PUBLIC;
원인 6: 대소문자 / 특수문자 문제 (드물지만 강력함)
오라클은 객체명을 자동으로 대문자로 저장합니다. 그런데 객체 생성 시 따옴표로 감싸면 대소문자가 그대로 저장되어 case-sensitive해집니다.
시나리오
-- 따옴표로 감싸서 생성 (의도적이든 실수든)
CREATE TABLE "employees" (id NUMBER); -- 소문자로 저장됨
-- 일반 접근 시
SELECT * FROM employees; -- ❌ ORA-00942 (대문자 EMPLOYEES를 찾음)
-- 정확히 접근하려면
SELECT * FROM "employees"; -- ✅ 가능
진단 방법
-- 대소문자 그대로 확인
SELECT owner, object_name, object_type
FROM dba_objects
WHERE object_name LIKE '%mployee%';
object_name이 EMPLOYEES가 아니라 employees처럼 소문자로 보이면 case-sensitive 객체입니다.
해결 방법
가능하면 객체명을 표준화(대문자) 하세요.
-- 기존 객체 이름 변경
ALTER TABLE "employees" RENAME TO employees;
운영 중인 환경이라면 시노님으로 우회 가능합니다.
CREATE SYNONYM employees_std FOR "employees";
빠른 해결 체크리스트 (종합)
5분 안에 원인을 좁히는 종합 체크리스트입니다.
순서 확인 항목 명령어
| 1 | DBA로 객체 존재 여부 | SELECT owner, object_name FROM dba_objects WHERE object_name = UPPER('객체명'); |
| 2 | 어느 스키마에 있는가 | 위 쿼리의 owner 컬럼 확인 |
| 3 | 직접 권한이 있는가 | SELECT * FROM user_tab_privs WHERE table_name = '객체명'; |
| 4 | ROLE 권한이 있는가 | SELECT * FROM role_tab_privs WHERE role IN (SELECT granted_role FROM user_role_privs); |
| 5 | PL/SQL 안에서 발생했는가 | DEFINER vs INVOKER, 직접 GRANT 필요 |
| 6 | 시노님이 깨졌는가 | SELECT * FROM all_synonyms WHERE synonym_name = '객체명'; |
그래도 안 풀린다면
위 6가지로도 해결되지 않는 드문 케이스:
- VPD(Virtual Private Database) / Row-Level Security: 보안 정책으로 특정 사용자에게 객체가 숨겨져 있는 경우
- 컨테이너 컨텍스트 오류 (12c+ 멀티테넌트): CDB$ROOT에서 PDB의 객체에 접근하려는 경우. ALTER SESSION SET CONTAINER = PDB명; 필요
- 객체가 RECYCLEBIN에 있음: 누군가 DROP했지만 PURGE는 안 한 상태. SELECT * FROM recyclebin;으로 확인 가능
- DBLINK 끊김: 원격 객체 접근 시 DBLINK가 끊어진 경우. SELECT * FROM user_db_links; 확인
마무리
ORA-00942는 메시지는 단순하지만 원인의 폭이 매우 넓은 에러입니다. "객체가 없다"라기보다 "내게 보이지 않는다" 로 사고를 전환하면 진단이 훨씬 정확해집니다.
특히 PL/SQL 내부에서 발생하는 ORA-00942는 90% 이상이 ROLE을 통한 권한 부여 때문입니다. 운영 환경에서 프로시저 컴파일이 갑자기 안 되면 가장 먼저 이걸 의심하세요.
권한 관리는 처음 설계할 때 ROLE 기반과 직접 GRANT의 트레이드오프를 미리 고려하는 것이 중요합니다. 신규 DB 구축 시 권한 모델을 표준화해 두면 ORA-00942로 인한 운영 사고를 크게 줄일 수 있습니다.
비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.
'DBA 실무 > Oracle(오라클)' 카테고리의 다른 글
| [오라클 에러] ORA-12514 TNS:리스너가 서비스를 알지 못함 - 5가지 원인과 해결방법 (PDB 환경 포함) (0) | 2026.06.05 |
|---|---|
| [오라클 실무] DBMS_SCHEDULER로 프로시저를 6시간 단위 실행하기 - 동적 인자 전달 완벽 예제 (0) | 2026.06.01 |
| [오라클] DBMS_JOB과 DBMS_SCHEDULER 차이점 - 언제 뭘 써야 할까? (19c 변환 동작까지) (0) | 2026.06.01 |
| [오라클 에러] ORA-28000 계정이 잠겼습니다 - 잠금 해제부터 재발 방지까지 (실무 DBA 정리) (0) | 2026.05.30 |
| [오라클 에러] ORA-01017 사용자명/비밀번호 무효 - 6가지 원인과 해결방법 (12c, 19c, 21c 차이까지) (0) | 2026.05.29 |