기본 콘텐츠로 건너뛰기

Oracle 전체 테이블 삭제 및 DB 링크 복제 자동화: PL/SQL 실전 스크립트 정리

Oracle DB 전체 테이블 삭제 및 DB 링크로 테이블·데이터 복사 자동화하기

개발·운영 환경을 초기화하거나, 다른 서버의 스키마를 그대로 복제해야 할 때 “전체 테이블 삭제 → DB 링크를 이용한 테이블/데이터 복사” 작업이 자주 필요합니다.

이 글에서는 Oracle 데이터베이스 기준으로 PL/SQL 루프 + EXECUTE IMMEDIATE를 활용해 전체 테이블 삭제와 DB 링크를 통한 테이블/데이터 복사를 자동화하는 방법을 정리합니다. 실무에서 바로 쓸 수 있는 예제 코드와, 꼭 확인해야 할 주의사항까지 함께 담았습니다.


1. Oracle DB 전체 테이블 삭제 (user_tables 기반)

개발 환경을 초기화하거나, 테스트용 스키마를 리셋할 때 user_tables 기준으로 현재 스키마의 모든 테이블을 DROP하는 패턴입니다. 아래 예제는 PL/SQL 블록 + 커서 루프로 구현한 기본 형태입니다.


BEGIN
   FOR c IN (SELECT table_name FROM user_tables) LOOP
      EXECUTE IMMEDIATE 'DROP TABLE ' || c.table_name || ' CASCADE CONSTRAINTS';
   END LOOP;
END;
/
    

1-1. 코드 설명

  • user_tables : 현재 접속한 유저가 소유한 테이블 목록을 반환
  • FOR c IN (...) : 각 테이블 이름을 하나씩 순회
  • EXECUTE IMMEDIATE : 동적 SQL 실행 (DROP TABLE 문을 문자열로 구성)
  • CASCADE CONSTRAINTS : 외래키 등 제약조건까지 함께 삭제
⚠️ 주의
이 코드는 현재 스키마의 모든 테이블을 삭제합니다.
운영 환경(Production)에서는 절대 사용 금지이며, 반드시 개발/로컬/테스트 환경에서만 사용하세요.

테이블 이름에 대소문자/특수문자가 섞여 있는 경우에는 "'||c.table_name||'"처럼 더블 쿼트로 감싸는 패턴도 많이 사용합니다.


2. DB 링크로 테이블 구조만 복사하기

다른 DB 서버나 스키마에 있는 테이블 구조만 먼저 가져오고 싶을 때, DB LINK를 통해 CREATE TABLE AS SELECT (CTAS) 문을 자동으로 생성하는 패턴입니다.

아래 예제는 DB 링크 이름이 TEST라고 가정합니다.


BEGIN
   FOR c IN (SELECT table_name FROM user_tables@TEST) LOOP
      EXECUTE IMMEDIATE
         'CREATE TABLE ' || c.table_name ||
         ' AS SELECT * FROM ' || c.table_name || '@TEST WHERE 1 = 2';
   END LOOP;
END;
/
    

2-1. 코드 설명

  • user_tables@TEST : DB 링크 TEST를 통해 원본 DB의 테이블 목록 조회
  • CREATE TABLE ... AS SELECT * ... WHERE 1 = 2 : 구조만 복사하고 데이터는 가져오지 않는 CTAS 패턴
  • 루프를 돌며 모든 테이블을 현재 스키마에 생성
💡 알아두면 좋은 점
이 방식은 기본적으로 컬럼 구조와 데이터 타입만 복사합니다.
인덱스, 제약조건, 시퀀스, 트리거 등은 별도로 생성해줘야 합니다.

3. DB 링크로 테이블 데이터까지 복사하기

2번에서 테이블 구조를 다 만들어두었다면, 이번에는 DB 링크를 통해 원본 DB의 데이터를 INSERT하는 작업을 자동화할 수 있습니다.

마찬가지로 DB 링크 이름은 TEST로 가정합니다.


BEGIN
   FOR c IN (SELECT table_name FROM user_tables@TEST) LOOP
      EXECUTE IMMEDIATE
         'INSERT INTO ' || c.table_name ||
         ' SELECT * FROM ' || c.table_name || '@TEST';
   END LOOP;

   COMMIT;
END;
/
    

3-1. 자주 하는 실수 바로잡기

질문 코드에 종종 INSERT INTO 테이블 AS SELECT ... 형태로 쓰는 경우가 있는데, INSERT 문에는 AS를 사용하지 않습니다.
올바른 문법은 다음과 같습니다.


-- 잘못된 예
INSERT INTO 테이블 AS SELECT * FROM 테이블@TEST;

-- 올바른 예
INSERT INTO 테이블 SELECT * FROM 테이블@TEST;
    

3-2. 코드 설명 및 주의사항

  • INSERT INTO <local_table> SELECT * FROM <remote_table>@TEST
    ⇒ DB 링크를 통해 원본 데이터를 한 번에 복사
  • 컬럼 순서가 동일해야 에러 없이 데이터가 들어갑니다.
  • 대량 데이터인 경우 COMMIT 주기를 나눠주는 것이 좋습니다.

DECLARE
   v_count NUMBER := 0;
BEGIN
   FOR c IN (SELECT table_name FROM user_tables@TEST) LOOP
      EXECUTE IMMEDIATE
         'INSERT INTO ' || c.table_name ||
         ' SELECT * FROM ' || c.table_name || '@TEST';

      v_count := v_count + 1;

      -- 예: 10개 테이블마다 한 번씩 커밋
      IF v_count MOD 10 = 0 THEN
         COMMIT;
      END IF;
   END LOOP;

   COMMIT;
END;
/
    

4. 실무에서 자주 쓰는 팁·주의사항

4-1. 특정 테이블 제외하기

로그 테이블, 대용량 히스토리 테이블 등은 복사 대상에서 제외하고 싶은 경우가 많습니다. 이때는 WHERE 절에 조건을 추가하면 됩니다.


FOR c IN (
   SELECT table_name
     FROM user_tables@TEST
    WHERE table_name NOT IN ('BIG_LOG_TABLE', 'BATCH_HISTORY')
) LOOP
   ...
END LOOP;
    

4-2. 인덱스·제약조건·시퀀스는 별도 스크립트로

  • CTAS로 생성한 테이블은 인덱스, PK/FK, 체크 제약조건, 트리거 등이 복사되지 않습니다.
  • user_constraints, user_indexes, user_sequences 등을 이용해 별도 스크립트를 생성하거나, DDL 추출 툴을 사용하는 것이 일반적입니다.

4-3. 권한 및 DB 링크 점검

  • 원본 DB에 대해 DB LINK가 정상적으로 연결되는지 사전 확인
  • 해당 스키마에 대한 SELECT 권한이 있는지 체크
  • 대량 데이터 복사 시 UNDO, TEMP, REDO 사용량 모니터링

4-4. 운영 환경에서는 신중하게

전체 테이블 삭제 및 대량 복사 작업은 운영환경에서는 치명적인 작업이 될 수 있습니다. 다음과 같은 원칙을 꼭 지키세요.

  • 반드시 테스트/스테이징 환경에서 충분히 검증 후 적용
  • 작업 전 전체 백업 또는 최소 테이블 레벨 백업 확보
  • 작업 시간, 롤백 플랜, 영향 범위를 문서화

이 글에서 소개한 코드는 Oracle 환경에서 스키마 초기화 + DB 링크 기반 테이블/데이터 복제를 빠르게 처리할 수 있는 기본 골격입니다.

실무에서는 여기서 한 단계 더 나아가, 제외 테이블 관리, 로그 기록, 에러 핸들링, 인덱스/제약조건 복원 스크립트까지 함께 구성하면 안정적인 마이그레이션·동기화 스크립트로 발전시킬 수 있습니다.

댓글

이 블로그의 인기 게시물

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 (Request Parameter 전체보기)

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 Java Servlet Request Parameter 완전 정복 웹 애플리케이션에서 클라이언트로부터 전달되는 Request Parameter 를 확인하는 것은 필수입니다. 이 글에서는 Java Servlet 과 JSP 에서 GET/POST 요청 파라미터를 전체 출력하고 디버깅하는 방법을 다양한 예제와 함께 소개합니다. 1. 기본 예제: getParameterNames() 사용 Enumeration<String> params = request.getParameterNames(); System.out.println("----------------------------"); while (params.hasMoreElements()){ String name = params.nextElement(); System.out.println(name + " : " + request.getParameter(name)); } System.out.println("----------------------------"); 위 코드는 요청에 포함된 모든 파라미터 이름과 값을 출력하는 기본 방법입니다. 2. HTML Form과 연동 예제 <form action="CheckParamsServlet" method="post"> 이름: <input type="text" name="username"><br> 이메일: <input type="email" name="email"><b...

PostgreSQL 달력(일별,월별)

SQL 팁: GENERATE_SERIES로 일별, 월별 날짜 목록 만들기 SQL 팁: GENERATE_SERIES 로 일별, 월별 날짜 목록 만들기 데이터베이스에서 통계 리포트를 작성하거나 비어있는 날짜 데이터를 채워야 할 때, 특정 기간의 날짜 목록이 필요할 수 있습니다. PostgreSQL과 같은 데이터베이스에서는 GENERATE_SERIES 함수를 사용하여 이 작업을 매우 간단하게 처리할 수 있습니다. 1. 🗓️ 일별 날짜 목록 생성하기 2020년 1월 1일부터 12월 31일까지의 모든 날짜를 '1 day' 간격으로 생성하는 쿼리입니다. WITH date_series AS ( SELECT DATE(GENERATE_SERIES( TO_DATE('2020-01-01', 'YYYY-MM-DD'), TO_DATE('2020-12-31', 'YYYY-MM-DD'), '1 day' )) AS DATE ) SELECT DATE FROM date_series 이 쿼리는 WITH 절(CTE)을 사용하여 date_series 라는 임시 테이블을 만들고, GENERATE_SERIES 함수로 날짜를 채웁니다. 결과 (일별 출력) 2. 📅 월별 날짜 목록 생성하기 동일한 원리로, 간격을 '1 MONTH' 로 변경하면 월별 목록을 생성할 수 있습니다. TO...

CSS로 레이어 팝업 화면 가운데 정렬하는 방법 (top·left·transform 완전 정리)

레이어 팝업 센터 정렬, 이 코드만 알면 끝 (CSS 예제 포함) 이벤트 배너나 공지사항을 띄울 때 레이어 팝업(center 정렬) 을 깔끔하게 잡는 게 생각보다 어렵습니다. 화면 크기가 변해도 가운데에 고정되고, 모바일에서도 자연스럽게 보이게 하려면 position , top , left , transform 을 정확하게 이해해야 합니다. 이 글에서는 아래 내용을 예제로 정리합니다. 레이어 팝업(center 정렬)의 기본 개념 자주 사용하는 position: absolute / fixed 정렬 방식 질문에서 주신 스타일 top: 3.25%; left: 50%; transform: translateX(-50%) 의 의미 실무에서 바로 쓰는 반응형 레이어 팝업 HTML/CSS 예제 1. 레이어 팝업(center 정렬)이란? 레이어 팝업(레이어 팝업창) 은 새 창을 띄우는 것이 아니라, 현재 페이지 위에 div 레이어를 띄워서 공지사항, 광고, 이벤트 등을 보여주는 방식을 말합니다. 검색엔진(SEO) 입장에서도 같은 페이지 안에 HTML이 존재 하기 때문에 팝업 안의 텍스트도 정상적으로 인덱싱될 수 있습니다. 즉, “레이어 팝업 센터 정렬”, “레이어 팝업 만드는 방법”과 같이 관련 키워드를 적절히 넣어주면 검색 노출에 도움이 됩니다. 2. 질문에서 주신 레이어 팝업 스타일 분석 질문에서 주신 스타일은 다음과 같습니다. <div class="layer-popup" style="width:1210px; z-index:9001; position:absolute; top:3.25%; left:50%; transform:translateX(-50%);"> 레이어 팝업 내용 <...