2016-06-09 53 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导入实用程序加载的文件。