2016-02-03 4 views
2

У меня есть таблица, состоящая из списка имен, разделенных запятой. Моя цель - разделить их номерами.Разбиение строки на несколько строк в Oracle 8i

Room | Name 
room1 | Anne,Amy 
room2 | Ben,Bryan 

Моя цель:

Room | Name 
room1 | Anne 
room1 | Amy 
room2 | Ben 
room2 | Bryan 

Я прочитал некоторые решения о том, как разделить строки на строки, но есть альтернативы для запуска на Oracle 8i. Я последовал ряд статей, чтобы разделить их на строки так:

create or replace function str2tbl(p_str IN varchar2 , p_delimiter in varchar2) return mytabletype 
    as 
    l_str  long default p_str || p_delimiter; 
    l_n  number; 
    l_data mytabletype := mytabletype(); 
    begin 
    loop 
    l_n := instr(l_str, p_delimiter); 
    exit when (nvl(l_n,0) = 0); 
    l_data.extend; 
    l_data(l_data.count) := ltrim(rtrim(substr(l_str,1,l_n-1))); 
    l_str := substr(l_str, l_n+1); 
    end loop; 
    return l_data; 
    end str2tbl; 

Тогда я ОТБОРНЫЙ из моей таблицы, как показано ниже:

select * from the (select cast(str2tbl(Name, ',') as mytableType) 
from SPLITSTRING); 

и получил результат ниже, но не могу вывести значения номера столбец:

Name 
Anne 
Amy 
Ben 
Bryan 

Есть ли способ разделить на строки в Oracle 8i?

ответ

0

Я не уверен, если это поддерживается в 8i, я испытал это в 12с, и он работает отлично:

create table test (room varchar2(20), names varchar2(40)); 

Таблица «тест» создан

insert into test values ('room1', 'anne'); 

INSERT INTO испытание успеха 1 ряд пострадавших

insert into test values ('room2', 'amy,sheldon'); 

вставить в тесте успешного 1 ряд пострадавших

insert into test values ('room3', 'penny,leonard'); 

INSERT INTO тест успешного 1 ряд пострадавших

Использование XMLTABLE:

SELECT room, 
trim(COLUMN_VALUE) names 
FROM test, 
xmltable(('"' 
|| REPLACE(names, ',', '","') 
|| '"')) 
/

ROOM | ИМЕНА


room1 | anne

room2 | ами

room2 | sheldon

room3 | penny

room3 | leonard

+0

вы можете найти некоторые другие способы для достижения своей цели здесь: Http: // StackOverflow.com/questions/14328621/splitting-string-into-multiple-rows-in-oracle –

+0

'XmlTable' поддерживается только в 10g и выше; связанное решение использует 'regexp_substr', даже не поддерживается в 8i – Aleksej

+0

hi krishna, Aleksej, спасибо за информацию. Я попробую его без использования connect или regexp. – abigal689

1

Вы можете попробовать несколько иначе, без функций, с помощью hierarchical queries и функций манипуляции струнами. Немного сложнее, но это должно работать:

with test (Room, Name) as 
(
select 'room2', 'Ben,Bryan' from dual 
) 
select room, 
     trim (',' from substr(name, 
           decode (level, 
             1, 1, 
              instr(name, ',', 1, level -1) +1 
            ), 
           decode (instr(name, ',', 1, level), 
             0, length(name), 
              instr(name, ',', 1, level) - 
               decode (level, 
                 1, 1, 
                  instr(name, ',', 1, level -1) 
                 ) 
            ) 
          )   
      ) as name 
from test 
connect by level = 1 or instr(name, ',', 1, level-1) != 0 
order by 1 
+0

Hi Aleksej, я тоже пробовал этот путь. но продолжайте получать «CONNECT BY loop в пользовательских данных», и я еще не понял эту ошибку. – abigal689

+0

Возможно, вы каким-то образом изменили его? Просто протестировано в 11g, оно работает, но не может попробовать на 8i. Если тот же код не работает для вас, то я использовал то, что не поддерживалось в 8i, даже если все используемые мной функции можно использовать в 8i – Aleksej

0

Вот альтернатива без использования подключения по

drop table pivot_t; 
drop table rooms; 

create table rooms (Room varchar2(30), Persons varchar2(30)); 

insert into rooms values ('room1', 'Anne,Amy'); 
insert into rooms values ('room2', 'Ben,Bryan,Paul'); 
insert into rooms values ('room3', 'John,Michael,Nik,Patrick'); 

create table pivot_t(num integer); 

begin 
for i in 1..10000 loop 
insert into pivot_t values(i); 
end loop; 
end; 
/

commit; 



select 
room 
,substr(Persons, start_pos, case 
    when 
    next_comma - start_pos < 0 then 999 
    else 
    next_comma - start_pos 
end) 
from 
(
select r.room 
     ,r.persons 
     ,nvl(instr(r.Persons,',',1,decode(pt.num-1,0,null,pt.num-1)),0) +1 START_POS 
     ,instr(r.Persons,',',1,pt.num) NEXT_COMMA 
    from rooms r 
     ,pivot_t pt 
where length(r.Persons) - length(replace(r.Persons,',')) +1 >= pt.num 
order by r.room, pt.num 
) 
; 
Смежные вопросы