Файл управления загрузчиком Oracle SQL: Заголовок загрузки в другой таблице с использованием, КОГДА

#sql #oracle #sql-loader #controlfile

Вопрос:

Я получаю файл, в котором есть:

  • заголовок, начинающийся со строкового заголовка, за которым следуют некоторые столбцы;
  • тело: все остальные строки после первой (заголовок).

Я знаю, что только заголовок будет начинаться со строки «ЗАГОЛОВОК», поэтому я подумал, что могу проверить его, используя условие 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»).

Глядя на журнал, кажется, что он читает структуру двух таблиц, игнорируя «где», как будто это содержимое одной таблицы, потому что у меня есть:

  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"
 

Итак, второй начинается со СЛЕДУЮЩЕГО, а не с ПЕРВОГО, так что я думаю, что все столбцы сдвинуты.

Я попытался добавить «ПОЗИЦИЯ(1) ЗАПОЛНИТЕЛЬ» для второй таблицы, но я получаю другие ошибки о типах.

Что не так в моем контрольном файле?

Ответ №1:

Вот упрощенный пример того, что вы делаете. Почему упрощенный? Потому что вы не предоставили тестовый пример, и мне не хотелось так много печатать.

Примеры таблиц:

 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),
 

Как вы можете видеть, были загружены обе таблицы, содержащие все примеры строк.