我正在使用外部表来从文件加载数据。这个数据有很多需要经过的处理,外部表是动态创建的,所以数据应该被加载到外部表中,然后进入全局临时表,然后删除外部表并进行处理继续临时表中的数据。临时表的结构与外部表的结构匹配。
删除外部表正在清除全局临时表。
这一切都发生在同一个过程中,所以我不认为这是一个会话问题。
proc看起来像这样:
create or replace
PROCEDURE Upload_Data_File
(
filename IN varchar2
)
IS
can_create_table char(1) := 'Y';
ext_table_name varchar2(200) := filename;
sql_to_run varchar(5000) := '';
BEGIN
/*****************************************************************************
Create external table/load file data
*****************************************************************************/
BEGIN
ext_table_name := replace(ext_table_name, '.', '_');
ext_table_name := 'ext_' || ext_table_name;
sql_to_run := 'CREATE TABLE ' || ext_table_name || '
(
ROW1 CHAR(1 BYTE),
ROW2 CHAR(1 BYTE),
RECORD_TEXT VARCHAR2(200 BYTE),
RECORD_NUMBER NUMBER
)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY FILE_DIRECTORY
ACCESS PARAMETERS
(
RECORDS DELIMITED BY NEWLINE
FIELDS
(
ROW1 char(1)
,ROW2 char(1)
,record_text position(3:203)
,record_number recnum
)
)
LOCATION
(
''' || filename || '''
)
)
REJECT LIMIT UNLIMITED';
EXECUTE IMMEDIATE sql_to_run;
can_create_table := 'Y';
END;
IF can_create_table = 'Y' THEN
/***************************************************************************
To avoid the use of a lot of dynamic SQL, a single statement will move
the rows from the external table to a global temp table.
***************************************************************************/
sql_to_run := 'INSERT INTO Global_File_Upload (
ROW1,
ROW2,
record_text,
record_number
)
SELECT
ROW1,
ROW2,
record_text,
record_number
FROM ' || ext_table_name;
EXECUTE IMMEDIATE sql_to_run;
/***************************************************************************
The external table is no longer needed and can be dropped
***************************************************************************/
sql_to_run := 'DROP TABLE ' || ext_table_name;
--EXECUTE IMMEDIATE sql_to_run;
/***************************************************************************
Process the records in the temp table
***************************************************************************/
END IF;
END IF;
只要注释掉用于删除外部表的EXECUTE IMMEDIATE,该过程就会正确运行。但是如果我允许该语句运行,那么临时表中没有要处理的数据。
答案 0 :(得分:6)
我的赌注是全局临时表定义为ON COMMIT DELETE ROWS
而不是ON COMMIT PRESERVE ROWS
。由于DDL像创建或删除表一样隐式提交,因此当事务结束时删除行的全局临时表将在会话中执行任何DDL时清除其数据。如果要保留数据,则需要将表定义为ON COMMIT PRESERVE ROWS
。
退一步说,这个架构似乎有问题。动态创建和删除对象几乎不是合适的解决方案。从您发布的示例中,您似乎正在删除并创建外部表,只是为了更改您正在加载的文件。最好只保留表并更改文件名
ALTER TABLE external_table_name
LOCATION( '<<new file name>>' );
您似乎不太可能希望将数据加载到临时表中,而不是直接查询外部表。除非你在临时表上构建索引以便提高处理效率,否则临时表不会为你买任何东西。但是,来自外部文件的大多数加载只是对数据进行一次传递,以便加载到永久表中。