使用 Oracle Ref Cursor 时出错
Error using Oracle Ref Cursor
我正在尝试做一些相当简单的事情,我正在尝试从我的个人 table space 中自动删除和备份 tables。我有大约 100 个 table 并想摆脱所有这些(我用来存储 table 名称的 table 除外),但想保留来自tables 以防将来我需要它们。下面是我试图用来完成此操作的代码。我在引用游标上收到错误,我将在我的代码下方包含该错误。我希望有人告诉我我是个白痴,并解释一种更简单的方法来做到这一点。如果不是,请告诉我我这样做的方式有什么问题,谢谢。
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:
感谢您的帮助。
至少,utl_file.put_line
不会获取任意记录,您不能将任意列列表提取到 varchar2
中。
您可以遍历每一列并构建一个 SQL 语句,将每一列的值连接成一个字符串。这将包括做一些事情,比如在你的 date
或 timestamp
列上放置一个带有显式格式掩码的 to_char
,添加一个分隔符,转义数据中存在的任何分隔符,等等。这是通常是一个相当乏味且容易出错的过程。然后您需要编写一个 SQL*Loader
控制文件以在将来加载数据。
听起来您最好使用 Oracle 导出实用程序导出 table。这是一个命令行实用程序(exp
或 expdp
取决于您是要使用经典版本还是 DataPump 版本),它允许您将 table 定义和数据导出到一个文件您可以稍后使用 Oracle 导入实用程序加载。
我正在尝试做一些相当简单的事情,我正在尝试从我的个人 table space 中自动删除和备份 tables。我有大约 100 个 table 并想摆脱所有这些(我用来存储 table 名称的 table 除外),但想保留来自tables 以防将来我需要它们。下面是我试图用来完成此操作的代码。我在引用游标上收到错误,我将在我的代码下方包含该错误。我希望有人告诉我我是个白痴,并解释一种更简单的方法来做到这一点。如果不是,请告诉我我这样做的方式有什么问题,谢谢。
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:
感谢您的帮助。
至少,utl_file.put_line
不会获取任意记录,您不能将任意列列表提取到 varchar2
中。
您可以遍历每一列并构建一个 SQL 语句,将每一列的值连接成一个字符串。这将包括做一些事情,比如在你的 date
或 timestamp
列上放置一个带有显式格式掩码的 to_char
,添加一个分隔符,转义数据中存在的任何分隔符,等等。这是通常是一个相当乏味且容易出错的过程。然后您需要编写一个 SQL*Loader
控制文件以在将来加载数据。
听起来您最好使用 Oracle 导出实用程序导出 table。这是一个命令行实用程序(exp
或 expdp
取决于您是要使用经典版本还是 DataPump 版本),它允许您将 table 定义和数据导出到一个文件您可以稍后使用 Oracle 导入实用程序加载。