2

我正在使用外部表从文件中加载数据。这个数据需要经过很多处理,并且外部表是动态创建的,所以数据应该是加载到外部表中,然后进入全局临时表,然后删除外部表并进行处理继续处理临时表中的数据。临时表的结构与外部表的结构相匹配。

删除外部表正在清除全局临时表。

这一切都发生在同一个过程中,所以我认为这不是会话问题。

过程看起来像这样:

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 被注释掉,该过程就可以正确运行。但是,如果我允许该语句运行,则临时表中没有要处理的数据。

4

1 回答 1

6

我的赌注是全局临时表被定义为ON COMMIT DELETE ROWS而不是ON COMMIT PRESERVE ROWS. 由于 DDL 喜欢创建或删除表隐式提交,因此在事务结束时删除行的全局临时表将在会话中执行任何 DDL 时清除其数据。如果要保留数据,则需要将表定义为ON COMMIT PRESERVE ROWS.

但是,退后一步,该架构似乎有问题。动态创建和删除对象几乎从来都不是合适的解决方案。从您发布的示例中,您似乎正在删除并创建外部表只是为了更改您从中加载的文件。最好只保留表格并更改文件名

ALTER TABLE external_table_name
  LOCATION( '<<new file name>>' );

您似乎也不太可能希望将数据加载到临时表中,而不仅仅是直接查询外部表。除非您在临时表上构建索引以提高处理效率,否则临时表不会给您带来任何好处。但是,大多数来自外部文件的加载只是对数据进行一次传递,以便加载到永久表中。

于 2013-11-07T01:17:12.467 回答