删除外部表会清除从外部表填充的全局临时表

时间:2013-11-06 23:52:54

标签: sql plsql oracle11g

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

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

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

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,该过程就会正确运行。但是如果我允许该语句运行,那么临时表中没有要处理的数据。

1 个答案:

答案 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>>' );

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