Записки жертвы высоких технологий

    Здравствуйте! Мой блог посвящен в большей своей части моей профессиональной деятельности на поприще использования технологий ORACLE для разработки баз данных OLTP и OLAP хранилищ данных. В заметках я периодически размещаю разнообразные SQL, PL/SQL и Java скрипты написанные мной и не только мной, ссылки на интересные источники в сети либо другую полезную информацию, которая каким либо образом касается моей работы с замечательными продуктами компании ORACLE.
    Вы можете связаться со мной по контактному емейлу, если у вас есть какие-либо вопросы, связанные с разработкой баз данных на основе продуктов ORACLE, буду рад помочь вам, если это будет в моих силах.

19 сент. 2025 г.

Парсинг большого CLOB значения в SQL построчно

Возникла у меня потребность поработать в SQL с данными, находящимися в строках CLOB значения, записанного в разных строках в таблице БД. Для этого нужны было разобрать данные в CLOB построчно, разбивая по символу chr(10), а затем сформировать столбцы при помощи regexp процедур. 
У вас похожая задача может, например, возникнуть, если вы храните CSV файл в  какой нибудь таблице БД, например такой TABWITHCSV (ID NUMBER, CSV_DATA CLOB), а структура CSV данных вам некоторым образом известна (хотя это не так уж и важно). Заполнена тестовая таблица вот таким образом:

select id, csv_data from TABWITHCSV
id        csv_data
     ----------------------------------
1       1,2,3,4,5
          6,7,8,9,10
2       a,b,c,d,e,f,g,h
          i,j,k,l,m,n,o,p

И вот приспичило вам например без всякого PL/SQL и каких либо сторонних средств выполнить запрос и вытащить эти данные в строки и столбцы результирующего набора. Как это сделать? 

Да вот так:

with
    q_data as (select id, csv_data from TABWITHCSV),
    q_xml_data as (select id, xmltype('<?xml version="1.0" encoding="UTF-8"?><root><csv>'||dbms_xmlgen.convert(csv_data)||'</csv></root>') as xml_data, chr(10) as delimiter from q_data),
    q_parsed_rows_data as (
        select 
            id, row_number() over(partition by id order by 1) line_no, xt.line_text
        from 
            q_xml_data d,
            xmltable(
                'for $text in tokenize($input, $delimiter) return $text' 
                passing d.xml_data as "input", d.delimiter as "delimiter" 
                columns line_text varchar2(4000) path '.'
            ) xt
    )
select 
    id, 
    line_no, 
    regexp_substr(line_text, '[^,]+',1,1) col_a, 
    regexp_substr(line_text, '[^,]+',1,2) col_b, 
    regexp_substr(line_text, '[^,]+',1,3) col_c, 
    regexp_substr(line_text, '[^,]+',1,4) col_d, 
    regexp_substr(line_text, '[^,]+',1,5) col_e,
    regexp_substr(line_text, '[^,]+',1,6) col_f,
    regexp_substr(line_text, '[^,]+',1,7) col_g,
    regexp_substr(line_text, '[^,]+',1,8) col_h
from 
    q_parsed_rows_data 
order by 
    id, line_no

Выполнив такой запрос вы получите поименованные данные из хранимых CLOB значений с идентификатором файла и номером строки