Извлечь данные CLOB для вставки - PullRequest
0 голосов
/ 07 июля 2019

У меня есть такие данные CLOB:

123456 (LED TV); 234543 (LED light); 654876 (LED monitor);

Теперь мне нужно извлечь все 6-значные номера (номер отслеживания счета в моем случае) из CLOB, используя разделитель (в моем случае "; ") и выберите этот параметр для вставки в целевую таблицу, но только если запись не существует.

Я видел пару примеров с Instr & Substr или Regexp, но ничего, что мне нужно, или помимо моего понимания Oracle.Может кто-нибудь показать мне пример того, как разбить CLOB на строки, основанные на строке внутри CLOB, чтобы использовать его для последующей вставки?

PS: Я бы предпочел самое быстрое решение, поскольку мои данные CLOB могут содержать более 5 миллионовзаписей счетов-фактур.Это будет хранимая процедура, запущенная из C # в конце, но эта часть вызывает у меня головную боль ... За любую помощь - заранее спасибо!

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Я попытался выполнить задачу, используя пакет DBMS_LOB, чтобы преобразовать их в строки, разделенные на ";" , а затем выполнил некоторые строковые операции с ним для достижения результата.

Попробуйте следующее:

INSERT INTO INVOICE_CATEGORIZED 
SELECT TAB.INVOICE_NUMBER, TAB.INVOICE_NAME FROM
(SELECT 
TRIM(dbms_lob.SUBSTR(INVOICE_INN,6 ,1)) AS INVOICE_NUMBER, 

SUBSTR(INVOICE_INN, 
INSTR(INVOICE_INN, '(') + 1,
INSTR(INVOICE_INN, ')') - INSTR(INVOICE_INN, '(') - 1 )
 AS INVOICE_NAME

-- HERE INVOICE_INN IS STRING NOW, SO WE CAN DO STRING OPERATIONS ON IT ONWARD

FROM
(
-- DIVIDING ; SEPARATED CLOB TO INDIVIDUAL STRING
SELECT
    TRIM(CASE WHEN INVOICE_SINGLE.COLUMN_VALUE = 1 THEN
    dbms_lob.SUBSTR(INVOICE, 
    dbms_lob.INSTR(INVOICE,';',1,INVOICE_SINGLE.COLUMN_VALUE) - 1,
    1 
    )
    ELSE
    dbms_lob.SUBSTR(INVOICE, 
    dbms_lob.INSTR(INVOICE,';',1,INVOICE_SINGLE.COLUMN_VALUE) - 1
    - dbms_lob.INSTR(INVOICE,';',1,INVOICE_SINGLE.COLUMN_VALUE - 1),
    dbms_lob.INSTR(INVOICE,';',1,INVOICE_SINGLE.COLUMN_VALUE - 1) + 1)
    END) AS INVOICE_INN
FROM
    INVOICES T,
    TABLE ( CAST(MULTISET(
        SELECT
            LEVEL
        FROM
            DUAL
        CONNECT BY
            dbms_lob.INSTR(INVOICE,';',1,LEVEL) <> 0
    ) AS SYS.ODCINUMBERLIST) ) INVOICE_SINGLE)) TAB 
     WHERE NOT EXISTS (SELECT 1 FROM INVOICE_CATEGORIZED IC
    WHERE IC.INVOICE_NUMBER  = TAB.INVOICE_NUMBER
    AND IC.INVOICE_NAME = TAB.INVOICE_NAME)

db <> fiddle demo

Cheers !!

0 голосов
/ 07 июля 2019

Вот пример.

Тестовый пример первым; test таблица содержит исходные данные:

SQL> create table test (col clob);

Table created.

SQL> insert into test
  2    select '123456 (LED TV); 234543 (LED light); 654876 (LED monitor);' from dual union all
  3    select '665988 (Notebook); 987654 (Mouse); 445577 (Dead Pixel);'    from dual;

2 rows created.

SQL>

Target таблица будет содержать значения, извлеченные из источника:

SQL> create table target (itn number, name varchar2(20));

Table created.

SQL> -- This value shouldn't be inserted as it already exists in the TARGET table:
SQL> insert into target values (234543, 'LED light');

1 row created.

SQL>

Теперь кое-что полезное. Идея состоит в том, чтобы разбить значения столбцов на строки (это то, что делает часть regexp_substr в иерархическом запросе, а затем отделить значение идентификатора от имени (заключенного в скобки). Значения, существующие в целевой таблице, вставлять не следует. (поэтому запрос должен вставлять 5 строк):

SQL> insert into target (itn, name)
  2  with
  3  c2r as
  4    -- split column to rows, e.g. "123456 (LED TV)" is an example of such a row
  5    (select to_char(trim(regexp_substr(col, '[^;]+', 1, column_value))) val
  6     from test join table(cast(multiset(select level from dual
  7                                        connect by level <= regexp_count(col, ';')
  8                                       ) as sys.odcinumberlist)) on 1 = 1
  9    ),
 10  sep as
 11    -- separate ITN (invoice tracking nubmer) and NAME
 12    (select substr(val, 1, instr(val, ' ') - 1) itn,
 13            substr(val, instr(val, ' ') + 1) name
 14     from c2r
 15    )
 16  select s.itn, replace(replace(s.name, '(', ''), ')', '')
 17  from sep s
 18  -- don't insert values that already exist in the TARGET table
 19  where not exists (select null from target t
 20                    where t.itn = s.itn
 21                   );

5 rows created.

SQL>

Окончательный результат:

SQL> select * From target;

       ITN NAME
---------- --------------------
    234543 LED light
    123456 LED TV
    654876 LED monitor
    665988 Notebook
    987654 Mouse
    445577 Dead Pixel

6 rows selected.

SQL>
...