Много я ковырялся с разбиением строк на токены пока не натолкнулся на интересную задачку, связанную с разбиением CSV-значения на элементы и cross join полученных элементов с исходной записью. Для начала реализовал ее с помощью XMLTable, но такой способ требует подготовки исходного значения для использования в XMLTable, т.к. каждый элемент списка должен быть помещен в кавычки, например использование значения 'a,b,c,d,e' невозможно, но '"a","b","c","d","e"' вполне подходит. К сожалению, не всегда возможно изменять строку перед такой операцией, например из-за лимита длины буфера, как в моем случае. Я решил поискать альтернативные решения, которые позволяли бы выполнять cross join элементов без изменения исходной строки. В конце концов нашел на asktom.oracle.com прекрасный вариант, который меня полностью удовлетворил:
SQL> CREATE TABLE MY_TABLE(
2 R_ID int,
3 R_Site varchar(20),
4 R_Name varchar(20),
5 R_Role varchar(20)
6 );
Table created.
SQL>
SQL> INSERT INTO MY_TABLE(R_ID , R_Site , R_Name , R_Role )
2 VALUES ('1' , '123,-456,-789', 'qwer' , 'Owner');
1 row created.
SQL>
SQL> INSERT INTO MY_TABLE(R_ID , R_Site , R_Name , R_Role )
2 VALUES ('2' , '56,-741,-852', 'qaz' , 'Manager');
1 row created.
SQL>
SQL>
SQL> select
2 t.r_id,
3 t.r_name,
4 t.r_role,
5 regexp_substr(t.R_Site, '[^,]+', 1, commas.column_value) as site
6 from
7 MY_TABLE t,
8 table(cast(multiset(select level from dual connect by level <= regexp_count(t.R_Site, '[^,]+')) as sys.OdciNumberList)) commas;
R_ID R_NAME R_ROLE SITE
---------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------
1 qwer Owner -456
1 qwer Owner -789
1 qwer Owner 123
2 qaz Manager -741
2 qaz Manager -852
2 qaz Manager 56
6 rows selected.
Единственное, что я сделал с найденным примером, так это заменил невнятное выражение в CONNECT BY на приведенный в примере выше вызов regexp_count(...) и убрал секцию ORDER BY из-за зависания сессии.
Комментариев нет:
Отправить комментарий