首页 > 解决方案 > Oracle SQL Loader 控制文件:使用 WHEN 上传不同表中的标头

问题描述

我收到一个文件,其中包含:

我知道只有标题会以字符串“HEADER”开头,所以我想我可以在我的控制文件中使用 WHEN 条件检查它,这是必要的,因为我必须将标题的内容插入表中,并将正文插入另一个表,所以我创建了以下控制文件:

OPTIONS (READSIZE=512000000,bindsize=512000000,rows=64000, ERRORS=100000)
LOAD DATA
characterset UTF8 length semantics byte
REPLACE
INTO TABLE <TABLE_1>
WHEN (1:6) != 'HEADER'
fields terminated by "|"
TRAILING NULLCOLS
(
  ANNO                 INTEGER EXTERNAL,
  COD_PRODOTTO         CHAR(12) "TRIM (:COD_PRODOTTO)",
  DESCRIZIONE_PRODOTTO CHAR(254) "TRIM (SUBSTRB(:DESCRIZIONE_PRODOTTO,1,254))",
  COD_PADRE            CHAR(12) "TRIM (:COD_PADRE)",
  FOGLIA               CHAR(1) "TRIM (:FOGLIA)",
  COD_STRUTTURA        CHAR(10)  "TRIM (:COD_STRUTTURA)",
  TIPO_STRUTTURA       CHAR(10) "TRIM (:TIPO_STRUTTURA)"
)
INTO TABLE <TABLE_2>
WHEN (1:6) = 'HEADER'
fields terminated by "|"
TRAILING NULLCOLS
(
  HEADER               FILLER,
  ANNO                 INTEGER EXTERNAL,
  COD_STRUTTURA        CHAR(12)  "TRIM (:COD_STRUTTURA)",
  TIPO_STRUTTURA       CHAR(12) "TRIM (:TIPO_STRUTTURA)",
  TIPO_INVIO           CHAR(5) "TRIM (:TIPO_INVIO)",
  DATA_RICEZIONE       "sysdate"
)

但我知道正文行已正确插入,但标题行未正确插入(它说“ANNO”是一个无效数字,但不是)。

“酷”的部分是,如果我反转插入标题而不是正文的位置(再次无效的“ANNO”)。

查看日志,它似乎读取了忽略 where 的两个表的结构,就像它是单个表的内容一样,因为我有:

 Column Name                  Position   Len  Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
ANNO                                FIRST     *   |       CHARACTER
COD_PRODOTTO                         NEXT    12   |       CHARACTER
    SQL string for column : "TRIM (:COD_PRODOTTO)"
DESCRIZIONE_PRODOTTO                 NEXT   254   |       CHARACTER
    SQL string for column : "TRIM (SUBSTRB(:DESCRIZIONE_PRODOTTO,1,254))"
COD_PADRE                            NEXT    12   |       CHARACTER
    SQL string for column : "TRIM (:COD_PADRE)"
FOGLIA                               NEXT     1   |       CHARACTER
    SQL string for column : "TRIM (:FOGLIA)"
COD_STRUTTURA                        NEXT    10   |       CHARACTER
    SQL string for column : "TRIM (:COD_STRUTTURA)"
TIPO_STRUTTURA                       NEXT    10   |       CHARACTER
    SQL string for column : "TRIM (:TIPO_STRUTTURA)"
Table <TABLE_2>, loaded when 1:6 = 0X484541444552(character 'HEADER')
Insert option in effect for this table: REPLACE
TRAILING NULLCOLS option in effect
   Column Name                  Position   Len  Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
HEADER                               NEXT     *   |       CHARACTER
  (FILLER FIELD)
ANNO                                 NEXT     *   |       CHARACTER
COD_STRUTTURA                        NEXT    12   |       CHARACTER
    SQL string for column : "TRIM (:COD_STRUTTURA)"
TIPO_STRUTTURA                       NEXT    12   |       CHARACTER
    SQL string for column : "TRIM (:TIPO_STRUTTURA)"
TIPO_INVIO                           NEXT     5   |       CHARACTER
    SQL string for column : "TRIM (:TIPO_INVIO)"
DATA_RICEZIONE                       NEXT     *   |       CHARACTER
    SQL string for column : "sysdate"

所以第二个从 NEXT 而不是 FIRST 开始,所以我认为所有的列都被移动了。

我尝试为第二个表添加“POSITION(1) FILLER”,但我得到了关于类型的其他错误。

我的控制文件有什么问题?

标签: sqloraclesql-loadercontrolfile

解决方案


这是您正在执行的操作的简化示例。为什么要简化?因为你没有提供测试用例,我也不想输入那么多。

示例表:

SQL> create table t1_header
  2    (header               varchar2(10),
  3     anno                 number,
  4     cod_struttura        varchar2(10)
  5    );

Table created.

SQL> create table t2_body
  2    (anno                 number,
  3     cod_prodotto         varchar2(12),
  4     descrizione_prodotto varchar2(10)
  5    );

Table created.

SQL>

控制文件;它包含要加载的数据。我首先加载标题表,接下来是正文:

load data
infile *
replace
into table t1_header
when (1:6) = 'HEADER'
fields terminated by "|"
trailing nullcols
(header   filler,
 anno,
 cod_struttura
)

into table t2_body
when (1:6) <> 'HEADER'
fields terminated by "|"
trailing nullcols
(anno                  position(1),
 cod_prodotto,
 descrizione_prodotto
)

begindata
HEADER|2021|test 1
2019|test2|descr t2
2020|test3|descr t3

加载会话和结果:

SQL> $sqlldr scott/tiger control=test1.ctl log=test1.log

SQL*Loader: Release 11.2.0.2.0 - Production on Pon Ruj 27 19:27:14 2021

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Commit point reached - logical record count 2
Commit point reached - logical record count 3

SQL> select * From t1_header;

HEADER           ANNO COD_STRUTT
---------- ---------- ----------
                 2021 test 1

SQL> select * From t2_body;

      ANNO COD_PRODOTTO DESCRIZION
---------- ------------ ----------
      2019 test2        descr t2
      2020 test3        descr t3

SQL>

在我看来,关键时刻是指示 SQL*Loader 再次重新处理同一个文件。如何?通过设置position

(anno                  position(1),

如您所见,两个表都已加载,包含所有示例行。


推荐阅读