Oracle Regexp_ help для замены строки

У меня есть поле с несколькими значениями имени, разделенными $;, как показано ниже:

$;James$;Paul$;

У меня есть функция, доступная для имен, которая позволяет мне идентифицировать данные из другой таблицы, то есть адреса электронной почты. Однако функция работает только с одним значением имени. Поэтому мне нужно создать подстроку, чтобы получить каждое значение имени, а затем запустить команду replace, которая запускает функцию для получения их адреса электронной почты. Я хочу получить следующие ответы: [email protected], [email protected].

Итак, мой вопрос: как я могу запустить команду regexp_replace, чтобы идентифицировать имена, а затем разделить их для выполнения замены?


person James Melville    schedule 07.02.2017    source источник


Ответы (2)


Что-то вроде этого:

with
     name_list ( id, str ) as (
       select 1, '$;James$;Paul$;'      from dual union all
       select 2, '$;Jane$;Emily$;Ann$;' from dual
     )
select id, substr(str, instr(str, '$;', 1, level) + 2,
              instr(str, '$;', 1, level+1) - instr(str, '$;', 1, level) - 2) as name
from   name_list
connect by level <= regexp_count(str, '\$;') - 1
       and prior id = id
       and prior sys_guid() is not null
;

ID   NAME
--   -----
 1   James
 1   Paul
 2   Jane
 2   Emily
 2   Ann

И затем вы можете использовать это для своих сравнений.

В качестве альтернативы, если вам нужно увидеть, находится ли имя James в вашей строке ввода (и предполагая, что James является значением в столбце name_col):

... where name_list.str like '$;' || name_col || '$;'

и вам больше не нужно разбивать строку. Однако конкатенации необходимы, потому что вы не хотите, чтобы Anne в списке имен совпадало с именем Ann в столбце.

person mathguy    schedule 07.02.2017

Эта функция помогает мне разбить varchar:

function f_split_string( p_string varchar2, p_separator varchar2, p_pos number) return varchar2
is
v_string varchar2(100);
begin
     select partition into v_string from
         (select rownum as n , partition from
             (select regexp_substr(p_string, '[^'||p_separator||']+', 1, level) partition from dual
             connect by regexp_substr(p_string, '[^'||p_separator||']+', 1, level) is not null)
         ) t1
     where t1.n = p_pos;

     return trim(v_string);
exception
    when others then return 'nfound';
end;

Пример вызова:

/*using the params*/
p_string := '$;James$;Paul$;'; --string to parse
p_separator := '$;'; --separator
p_pos := 1; --position to get
f_split_string(p_string,p_separator,p_pos) /*return 'James'*/

/*if p_pos :=2*/
f_split_string(p_string,p_separator,p_pos) /* return 'Paul' */

/*if p_pos :=3*/
f_split_string(p_string,p_separator,p_pos) /*return 'nfound' */

/*if p_pos :=0*/
f_split_string(p_string,p_separator,p_pos) /* return 'nfound' */
person Julian    schedule 07.02.2017
comment
Я боюсь, что ваше решение не обрабатывает элементы списка NULL и, если он встречается, вернет неправильные данные. Дайте '$;James$;$;Paul$;George' и попросите 3-ю позицию. Использование регулярного выражения '[^,]+' (как обычно встречается) опасно. stackoverflow.com/a/31464699/2543416 - person Gary_W; 07.02.2017