DBA 실무/Oracle(오라클)

[오라클 에러] ORA-00942 table or view does not exist - 6가지 원인과 해결방법 (권한과 PL/SQL 케이스까지)

isony 2026. 6. 8. 07:43
반응형

[오라클 에러] 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초 만에 원인을 좁히는 순서입니다.

  1. DBA 계정으로 객체 존재 여부 확인 → 정말 없는가, 아니면 보이지 않는가?
  2. 객체의 소유 스키마 확인 → 다른 스키마인가?
  3. 현재 사용자에게 SELECT 권한이 있는가
  4. PL/SQL 안에서 발생했는가 → ROLE 권한 문제일 가능성
  5. 객체가 INVALID 상태인가 → 의존성 깨진 뷰/시노님
  6. 객체 이름에 대소문자/특수문자 포함? → 따옴표 케이스

 

원인 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로 동작 안 한다면 다음을 의심하세요.

  1. 객체 소유자 또는 권한 부여가 변경됨
  2. ROLE에서 권한이 회수됨
  3. 참조하는 객체가 다른 스키마로 이동

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로 인한 운영 사고를 크게 줄일 수 있습니다.

비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.

 

 

반응형