2016-06-09 1 views
0

나는 간단한 작업을 시도하고 있습니다. 개인 테이블 공간에서 테이블을 자동으로 제거하고 백업하려고합니다. 나는 약 100 개의 테이블을 가지고 있고 (테이블 이름을 저장하기 위해 사용하는 테이블을 제외하고) 모든 것을 없애고 싶습니다. 그러나 미래의 언젠가 필요할 때를 대비하여 테이블의 데이터를 유지하려고합니다. 아래는 이것을 달성하기 위해 사용하려고하는 코드입니다. 참조 커서에 오류가 발생했습니다.이 오류는 내 코드 아래에 포함됩니다. 나는 절반이 누군가 내가 나에게 바보라고 말하고 이것을 쉽게하는 방법을 설명 할 것을 기대한다. 그렇지 않다면 내가하고있는 방식으로 잘못하고있는 것을 말해줘. 고마워. 어떤 도움Oracle Ref Cursor를 사용한 오류

Error report: 
ORA-00932: inconsistent datatypes: expected - got - 
ORA-06512: at line 73 
00932. 00000 - "inconsistent datatypes: expected %s got %s" 
*cause: 
*action: 

감사를 다음과 같이

DECLARE 
    v_folder_name  VARCHAR2(100) := 'MY_FOLDER'; 
    TYPE QRY_CURSOR  IS REF CURSOR; 
    v_qry_cursor   QRY_CURSOR; 
    v_file_name   VARCHAR2(320); 
    v_file    sys.utl_file.file_type; 
    v_max_buffer_length CONSTANT BINARY_INTEGER := 32767; 
    v_qry_str   VARCHAR2(4000); --I've tried this with 32767, made no difference 
    v_drop_string  VARCHAR2(4000); 
    v_dynamic_record  VARCHAR2(4000); --tried this with 32767 also 

CURSOR GET_TABLE_NAMES IS 
    SELECT * FROM TEMP_BACKUP_TABLE WHERE TABLE_NAME <> 'TEMP_BACKUP_TABLE'; 

FUNCTION startFile(file_name VARCHAR2) 
    --working function, used with many procedures, left out for brevity 
END startFile; 

FUNCTION closeFile(file_name VARCHAR2) 
    --working function, used with many procedures, left out for brevity 
END closeFile; 

BEGIN 
    INSERT INTO TEMP_BACKUP_TABLE SELECT DISTINCT TABLE_NAME FROM ALL_TAB_COLS WHERE OWNER = 'ME'; 
    COMMIT; 
FOR REC IN GET_TABLE_NAMES LOOP 
    v_file_name := REC.TABLE_NAME; 
    v_file := startFile(v_file_name); 
    v_qry_str := 'SELECT * FROM ' || v_file_name; 
    v_drop_string := 'DROP TABLE ' || v_file_name; 
    OPEN v_qry_cursor FOR v_qry_str; -- this is the line that returns an error 
    LOOP 
     FETCH v_qry_cursor INTO v_dynamic_record; 
     EXIT WHEN v_qry_cursor%NOTFOUND; 
     sys.utl_file.put_line(v_file, v_dynamic_record); 
    END LOOP; 

    CLOSE v_qry_cursor; 
    EXECUTE IMMEDIATE v_drop_string; 
    COMMIT; 

    v_file := closeFile(v_file_name); 
END LOOP; 
DELETE FROM TEMP_BACKUP_TABLE; 
END; 

내가 갖는 오류입니다.

+1

최소한 utl_file.put_line은 임의의 레코드를 취하지 않으므로 임의의 열 목록을'varchar2'로 가져올 수 없습니다. 각 열을 반복하고 각 열의 값을 단일 문자열로 연결하는 SQL 문을 구성 할 수 있습니다 ('date'또는 'timestamp'열에서 'to_char'를 수행하여 특정 형식으로 저장하는 작업 포함) . 하지만 많은 코드를 작성하는 대신 명령 행'exp' 또는'expdp' 실행 파일을 사용하여 테이블을 내보내는 것이 더 합리적 일 것입니다. –

+0

@JustinCave 알다시피, 내가 처음에 이것을 썼을 때 (오래전에) 나는 열을 문자열로 연결 시켰고, 어떤 이유로 그것을 변경했는데 생각조차하지 않았습니다. 이제 "누락 된 표현"오류가 발생하므로 SQL에 문제가 발생했습니다. 나는 지금 그것을 이해할 수있을 것이라고 확신한다. 답변으로 의견을 기재하면 동의하겠습니다. 감사. –

답변

1

최소한 utl_file.put_line은 임의의 레코드를 취하지 않으므로 varchar2에 임의의 열 목록을 가져올 수 없습니다.

각 열을 반복하고 각 열의 값을 단일 문자열로 연결하는 SQL 문을 구성 할 수 있습니다. 이는 date 또는 timestamp 열에 명시적인 형식의 마스크를 사용하여 to_char을 입력하고, 구분 기호를 추가하고, 데이터에 존재하는 구분 기호를 이스케이프 처리하는 등의 작업을 포함합니다. 이는 일반적으로 오히려 지루하고 오류가 발생하기 쉬운 프로세스입니다. 그리고 나서 나중에 데이터를로드하기 위해 SQL*Loader 제어 파일을 작성해야합니다.

오라클 익스포트 유틸리티를 사용하여 테이블을 내보내는 것이 더 좋습니다. 이는 Oracle 임포트 유틸리티를 사용하여 나중에로드 할 수있는 파일로 테이블 정의 및 데이터를 내보낼 수있는 명령 행 유틸리티 (기본 버전 또는 DataPump 버전 사용 여부에 따라 exp 또는 expdp)입니다.

관련 문제