Это можно сделать с помощью sqlldr. Я сделал некоторые предположения, но если данные представляют собой одну строку на строку, как вы описали выше, с тем же количеством элементов строки, правильно сконструированный управляющий файл с несколькими операторами «в таблицу» может писать разные части одной строки данных как несколько строк в одну и ту же таблицу.
Контроль файла:
LOAD DATA
infile "file.dat"
TRUNCATE
INTO TABLE data_table
(entirerow BOUNDFILLER char(4000)
,code expression "regexp_substr(:entirerow, '(.*?)(_)', 1, 1, NULL, 1)"
,desc expression "regexp_substr(:entirerow, '(.*?)(+)', 1, 3, NULL, 1)"
)
INTO TABLE data_table
(entirerow BOUNDFILLER position(1) char(4000)
,code expression "regexp_substr(:entirerow, '(.*?)(_)', 1, 1, NULL, 1)"
,desc expression "regexp_substr(:entirerow, '(.*?)(+)', 1, 5, NULL, 1)"
)
INTO TABLE data_table
(entirerow BOUNDFILLER position(1) char(4000)
,code expression "regexp_substr(:entirerow, '(.*?)(_)', 1, 1, NULL, 1)"
,desc expression "regexp_substr(:entirerow, '(.*?)(+)', 1, 9, NULL, 1) || ' ' ||
regexp_substr(:entirerow, '(.*?)(+|$)', 1, 10, NULL, 1)"
)
Пару вещей отметить:
Поскольку нет никаких ограничителей, и ничего не указано, то вся строка будет прочитана в первом поле «EntireRow» , Поскольку это не столбец в таблице, и он определен как BOUNDFILLER, он «запоминается» для использования позже.
Следующее поле «код» находится в файле управления. Поле данных не существует, но sqlldr находит, что он соответствует столбцу в таблице, и видит, что это выражение, поэтому оно применяет выражение с намерением поместить результат в столбец. Выражение использует REGEXP_SUBSTR против запоминающегося BOUNDFILLER, чтобы вырезать нужные нам части. Для кода введите символы до, но не включая первый символ подчеркивания. Для desc получите третий набор символов, за которым следует одно или несколько пробелов (но не пробелы).
Для второй логической строки нам нужно переместить логический указатель назад в начало строки, прочитанной так, чтобы sqlldr мог повторно обрабатывать. В противном случае логический указатель находится в конце данных, и ничего не будет возвращено. Это делается с параметром «позиция», указанным в определении «entirerow» второго и третьего «в таблицу». Последняя «в таблицу» следует предыдущей парадигме, просто получая 9-е и 10-е поля и объединяя их вместе. Я решил сделать это вместо того, чтобы придумать другое регулярное выражение, чтобы оно соответствовало другим полям, плюс, если вы хотите изменить его в будущем, будет легче следовать.
Как вы можете видеть, что это работает и многоразовые:
SQL> select code, desc
from data_table;
CODE DESC
------------------------- -------------
BANAC2C100017701007 4X2
BANAC2C100017701007 MLCR
BANAC2C100017701007 160 E4
Возможные нюанс: каждая строка сканируется в 3 раза, а регулярное выражение звонки стоят дорого, так в зависимости от объема данных, которые нужно загрузить этот не может быть приемлемым решением для вашей ситуации.
Можете ли вы использовать sqlldr? Имеют ли данные разделители или являются ли поля фиксированной длины? Или они, по крайней мере, имеют одинаковое количество элементов? –