Oracle Анализ данных NCLOB для вывода или новой таблицы - PullRequest
1 голос
/ 08 января 2020

У меня есть таблица Oracle 11.2.0.4.0 с именем LOOKUPTABLE с 3 полями

НОМЕР LOOKUPTABLEID (12) LOOKUPTABLENM NVARCHAR2 (255) LOOKUPTABLECONTENT NCLOB

Данные в поле NCLOB тщательно проверяются при вставке, поэтому я уверен, что данные всегда являются разделенной запятыми строкой с CRLF на конце, поэтому читается точно так же, как простой файл CSV. Пример ([CRLF] - представление фактического CRLF, а не текста)

WITH lookuptable AS (
SELECT
1 AS "LOOKUPTABLEID",
'CODES.TBL' AS "LOOKUPTABLENM",
TO_NCLOB('851,ALL HOURS WORKED GLASS,G,0,,,,,,'||chr(10)||chr(13)||
         '935,ALL OT AND HW HRS,G,0,,,,,,'||chr(10)||chr(13)||
         '934,ALL PAID TIME,G,0,,,,,,'||chr(10)||chr(13)) AS "LOOKUPTABLECONTENT"
FROM dual
)
SELECT lookuptablecontent FROM lookuptable WHERE lookuptablenm='CODES.TBL';

"851, ВСЕ ЧАСЫ РАБОТАЛИ СТЕКЛО, G, 0 ,,,,,, [CRLF] 935, ВСЕ OT И HW HRS, G, 0 ,,,,,, [CRLF] 934, ВСЕ ПЛАНИРОВАННОЕ ВРЕМЯ, G, 0 ,,,,,, [CRLF] "

По сути, я хочу получить запрос, который может выводить 1 строка для каждой строки в CLOB. Я использую приложение, которое будет читать этот SQL и записывать его в текстовый файл для меня, но оно не может обрабатывать типы данных CLOB, и у меня нет возможности записывать напрямую в файл из SQL. У меня должен быть запрос, который может дать этот результат и позволить моему приложению написать файл. У меня есть возможность создавать / записывать свои собственные таблицы, так что процедура, которая будет считывать CLOB в новую таблицу, а затем я буду выбирать из этой таблицы в моем приложении, будет приемлемой, если это лучше, прямо сейчас у меня над головой. Желаемый вывод ниже, заранее спасибо за любую помощь:)

1. 851,ALL HOURS WORKED GLASS,G,0,,,,,,
2. 935,ALL OT AND HW HRS,G,0,,,,,,
3. 934,ALL PAID TIME,G,0,,,,,,

Ответы [ 2 ]

1 голос
/ 09 января 2020

Мой пример данных и формат с использованием рекурсивного CTE без регулярного выражения по ссылке, предоставленной @ kfinity

WITH lookuptable (lookuptableid, lookuptablenm, lookuptablecontent) AS (
  SELECT
    1,
    'CODES.TBL',
    TO_NCLOB('ID,NAME,TYPE,ISMONEYSW,EARNTYPE,EARNCODE,RATESW,NEGATIVESW,OVERRIDEID,DAILYSW'||chr(13)||chr(10)||
             '851,ALL HOURS WORKED GLASS,G,0,,,,,,'||chr(13)||chr(10)||
             '935,ALL OT AND HW HRS,G,0,,,,,,'||chr(13)||chr(10)||
             '934,ALL PAID TIME,G,0,,,,,,'
              )
   FROM dual
), CTE (lookuptableid, lookuptablenm, lookuptablecontent, startposition, endposition) AS (
  SELECT
    lookuptableid,
    lookuptablenm,
    lookuptablecontent,
    1,
    INSTR(lookuptablecontent, chr(13)||chr(10))
   FROM lookuptable
   WHERE lookuptablenm = 'CODES.TBL'
  UNION ALL
  SELECT
    lookuptableid,
    lookuptablenm,
    lookuptablecontent,
    endposition + 1,
    INSTR(lookuptablecontent, chr(13)||chr(10), endposition+1)
   FROM CTE
   WHERE endposition > 0
)
SELECT
  lookuptableid,
  lookuptablenm,
  SUBSTR(lookuptablecontent, startposition, DECODE(endposition, 0, LENGTH(lookuptablecontent) + 1, endposition) - startposition) AS lookuptablecontent
 FROM CTE
ORDER BY lookuptableid, startposition;
1 голос
/ 08 января 2020

Это конкретный c случай общего вопроса "как разбить строку", и Я связываю этот вопрос много для более подробной информации об этом. В этом случае вместо запятой разделитель, на который вы хотите разделить, - это CRLF или chr(10)||chr(13).

. Вот простое решение с regexp_substr. Это не самое быстрое решение, но оно отлично работает в простом сценарии ios. Если вам нужна более высокая производительность, посмотрите версию по ссылке выше с рекурсивным CTE и без регулярных выражений.

WITH lookuptable AS (
SELECT
1 AS LOOKUPTABLEID,
'CODES.TBL' AS LOOKUPTABLENM,
TO_NCLOB('851,ALL HOURS WORKED GLASS,G,0,,,,,,'||chr(10)||chr(13)||
         '935,ALL OT AND HW HRS,G,0,,,,,,'||chr(10)||chr(13)||
         '934,ALL PAID TIME,G,0,,,,,,'||chr(10)||chr(13)) AS LOOKUPTABLECONTENT
FROM dual
)
SELECT lookuptableid as id, to_char(regexp_substr(lookuptablecontent,'[^('||chr(13)||chr(10)||')]+', 1, level))
FROM lookuptable 
WHERE lookuptablenm='CODES.TBL'
connect by level <= regexp_count(lookuptablecontent, '[^('||chr(13)||chr(10)||')]+')
and PRIOR lookuptableid =  lookuptableid and PRIOR SYS_GUID() is not null -- needed if more than 1 source row  
order by lookuptableid, level
;

Вывод:

id  r
1   851,ALL HOURS WORKED GLASS,G,0,,,,,,
1   935,ALL OT AND HW HRS,G,0,,,,,,
1   934,ALL PAID TIME,G,0,,,,,,
...