#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),
Как вы можете видеть, были загружены обе таблицы, содержащие все примеры строк.