Разбиение строчного значения на токены по нескольким разделителям в цикле

Есть переменная с типом данных nvarchar(max) содержащая текст:

номер1;текст1/nномер2;текст2/nномерN;текстN/n

Нужно в цикле заполнять переменные значениями номер1,текст1, затем номер2, тескт2 и т.д., чтобы в в каждой итерации цикла передавать их в функцию.

Как можно это сделать?


Ответы (2 шт):

Автор решения: Akina

Схематично:

WITH cte (one_fragment, slack)
AS ( SELECT SUBSTR(field, 1, INSTR(field || '\n', '\n') - 1) AS one_fragment,
            SUBSTR(field, INSTR(field || '\n', '\n') + 2, LENGTH(field)) AS slack
     FROM sourcetable
   UNION ALL
     SELECT SUBSTR(slack, 1, INSTR(slack || '\n', '\n') - 1),
            SUBSTR(slack, INSTR(slack || '\n', '\n') + 2, LENGTH(slack))
     FROM cte
     WHERE slack IS NOT NULL )
SELECT one_fragment
FROM cte;

Или что-то типа

SELECT REGEXP_SUBSTR(field,'\n', 1, level) 
FROM sourcetable
CONNECT BY REGEXP_SUBSTR(field, '\n', 1, level) IS NOT NULL;
→ Ссылка
Автор решения: 0xdb

Рабочее решение на чистом PL/SQL:

declare
    str varchar2 (32000) := 'номер1;текст1/nномер2;текст2/n';
    pattern constant varchar2 (64) := '(\w+);(\w+)/n';
    type pairRow is record (num varchar2 (16), txt varchar2 (16));
    pair pairRow;
    counter int := 0;
    function print (pair pairRow) return varchar2 is begin 
        return 'pair('||pair.num||','||pair.txt||')';
    end; 
begin
    <<split>> loop counter := counter+1;
        exit split when regexp_substr (str, pattern, 1, counter) is null;
        pair.num := regexp_substr (str, pattern, 1, counter, null, 1);
        pair.txt := regexp_substr (str, pattern, 1, counter, null, 2);
        dbms_output.put_line (print (pair));
    end loop;
end;
/

Результат:

pair(номер1,текст1)  
pair(номер2,текст2)

Можно заменить REGEX_SUBSTR на низкоуровневые SQl функции SUBSTR,INSTR, если обьём данных очень большой и важна производительность.
В любом случае, надо реализовать как функцию, чтобы вызов выглядел как-то так:

myFunc (getPair (str, counter))
→ Ссылка