2016-06-09 78 views
0

我正在嘗試做一些相當簡單的事情,我試圖自動從我的個人表空間中刪除和備份表。我有大約100個表,並希望擺脫所有這些表(我用來存儲表名的表除外),但希望保留表中的數據以防將來需要它們。以下是我正在嘗試用來完成此操作的代碼。我在ref光標上出現錯誤,我將在我的代碼下面包含該錯誤。我半期望有人告訴我,我是一個白癡,並解釋一個更簡單的方法來做到這一點。如果沒有,請告訴我我做錯了什麼,我正在做這件事,謝謝。錯誤使用Oracle參考光標

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; 

我得到的錯誤如下:

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

感謝您的幫助。

+1

至少,'utl_file.put_line'不會取任意記錄,並且不能將任意列列表讀取到'varchar2'中。你可以遍歷每一列,並構造一個SQL語句,將每列的值連接成單個字符串(包括像在'date'或'timestamp'列上做'to_char'來將它們保存爲特定格式) 。儘管如此,使用命令行'exp'或'expdp'可執行文件導出表似乎更有意義。 –

+0

@JustinCave你知道,當我第一次寫這個(很久以前),並且由於某種原因改變了它,甚至沒有想到的時候,我把它連接成一個字符串。現在我收到一個「缺少表達式」的錯誤,所以現在必須是SQL的問題。我相信我現在可以搞清楚了。如果你把你的評論作爲答案,我會接受它。謝謝。 –

回答

1

至少,utl_file.put_line不會取任意記錄,您不能將任意列列表取回到varchar2

您可以迭代每列,並構造一個SQL語句,將每列的值連接到單個字符串中。這包括在datetimestamp列上添加一個帶有明確格式掩碼的to_char,添加一個分隔符,轉義數據中存在的任何分隔符等。這通常是一個相當單調且容易出錯的過程。然後,您需要編寫一個SQL*Loader控制文件,以便將來加載數據。

聽起來你最好使用Oracle導出實用程序導出表。這是一個命令行實用程序(expexpdp,具體取決於您是使用傳統版本還是DataPump版本),它允許您將表定義和數據導出到稍後可以使用Oracle導入實用程序加載的文件。