Oracle PL/SQL에 문자열을 분할하는 기능이 있습니까?
여러 개의 토큰이 하나의 문자로 연결된 레코드를 정규화하기 위한 프로시저를 작성해야 합니다.문자열을 분할하는 토큰을 가져와 테이블에 새 레코드로 삽입해야 합니다.Oracle에는 "분할" 기능과 같은 기능이 있습니까?
있어apex_util.string_to_table
- 이 질문에 대한 내 답변을 확인합니다.
또, 상기의 기능이 존재하기 전에, 여기 블로그에 솔루션을 게재한 적이 있습니다.
갱신하다
APEX의 최신 버전에서는apex_util.string_to_table
는 권장되지 않습니다.또, 같은 함수 apex_string.html 가 권장됩니다.
한다면APEX_UTIL
사용할 수 없습니다. 솔루션을 사용하고 있습니다.REGEXP_SUBSTR()
.
http://nuijten.blogspot.fr/2009/07/splitting-comma-delimited-string-regexp.html에서 영감을 얻음:
DECLARE
I INTEGER;
TYPE T_ARRAY_OF_VARCHAR IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;
MY_ARRAY T_ARRAY_OF_VARCHAR;
MY_STRING VARCHAR2(2000) := '123,456,abc,def';
BEGIN
FOR CURRENT_ROW IN (
with test as
(select MY_STRING from dual)
select regexp_substr(MY_STRING, '[^,]+', 1, rownum) SPLIT
from test
connect by level <= length (regexp_replace(MY_STRING, '[^,]+')) + 1)
LOOP
DBMS_OUTPUT.PUT_LINE(CURRENT_ROW.SPLIT);
MY_ARRAY(MY_ARRAY.COUNT) := CURRENT_ROW.SPLIT;
END LOOP;
END;
/
직접 굴려야 돼.예.,
/* from :http://www.builderau.com.au/architect/database/soa/Create-functions-to-join-and-split-strings-in-Oracle/0,339024547,339129882,00.htm
select split('foo,bar,zoo') from dual;
select * from table(split('foo,bar,zoo'));
pipelined function is SQL only (no PL/SQL !)
*/
create or replace type split_tbl as table of varchar2(32767);
/
show errors
create or replace function split
(
p_list varchar2,
p_del varchar2 := ','
) return split_tbl pipelined
is
l_idx pls_integer;
l_list varchar2(32767) := p_list;
l_value varchar2(32767);
begin
loop
l_idx := instr(l_list,p_del);
if l_idx > 0 then
pipe row(substr(l_list,1,l_idx-1));
l_list := substr(l_list,l_idx+length(p_del));
else
pipe row(l_list);
exit;
end if;
end loop;
return;
end split;
/
show errors;
/* An own implementation. */
create or replace function split2(
list in varchar2,
delimiter in varchar2 default ','
) return split_tbl as
splitted split_tbl := split_tbl();
i pls_integer := 0;
list_ varchar2(32767) := list;
begin
loop
i := instr(list_, delimiter);
if i > 0 then
splitted.extend(1);
splitted(splitted.last) := substr(list_, 1, i - 1);
list_ := substr(list_, i + length(delimiter));
else
splitted.extend(1);
splitted(splitted.last) := list_;
return splitted;
end if;
end loop;
end;
/
show errors
declare
got split_tbl;
procedure print(tbl in split_tbl) as
begin
for i in tbl.first .. tbl.last loop
dbms_output.put_line(i || ' = ' || tbl(i));
end loop;
end;
begin
got := split2('foo,bar,zoo');
print(got);
print(split2('1 2 3 4 5', ' '));
end;
/
regexp_substr()을 사용할 수 있습니다.예:
create or replace type splitTable_Type is table of varchar2(100);
declare
l_split_table splitTable_Type;
begin
select
regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level)
bulk collect into
l_split_table
from dual
connect by
regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null;
end;
쿼리는 쉼표로 구분된 문자열을 반복하고 쉼표(,)를 검색한 다음 쉼표를 구분 기호로 처리하여 문자열을 분할합니다.딜리미터에 도달할 때마다 문자열이 행으로 반환됩니다.
level
진술로regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level)
는 계층형 쿼리에서 사용되는 Oracle의 의사 초콜릿으로, 계층형 레벨을 수치 형식으로 식별합니다.
이 기능은 Oracle 10G 이상에서만 작동합니다.
기본적으로는 regex_substr을 사용하여 문자열로 분할합니다.
편집:
아카이브 링크: http://web.archive.org/web/20170304121704/https://http://web.archive.org/web/20170304121704/https
코드:
select * from emp where ename in (
select regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) from dual
connect by regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null
);
다음과 같이, 기판과 INSTR 의 편성을 사용할 수 있습니다.
문자열 예:field = 'DE124028#@$1048708#@$000#@$536967136#@$'
분리기는 #@$입니다.
예를 들어 '1048708'을 얻으려면 다음과 같이 하십시오.
필드가 고정길이(여기서는 7)인 경우:
substr(field,instr(field,'#@$',1,1)+3,7)
필드의 길이가 가변인 경우:
substr(field,instr(field,'#@$',1,1)+3,instr(field,'#@$',1,2) - (instr(field,'#@$',1,1)+3))
유연성을 높이기 위해 아마 기판 및 INSTR 기능을 검토해야 할 것입니다.
다음에 도움이 될 만한 예를 찾아주세요.
--첫 번째 서브스트링
select substr('alfa#bravo#charlie#delta', 1,
instr('alfa#bravo#charlie#delta', '#', 1, 1)-1) from dual;
--두 번째 서브스트링
select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 1)+1,
instr('alfa#bravo#charlie#delta', '#', 1, 2) - instr('alfa#bravo#charlie#delta', '#', 1, 1) -1) from dual;
-- 세 번째 서브스트링
select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 2)+1,
instr('alfa#bravo#charlie#delta', '#', 1, 3) - instr('alfa#bravo#charlie#delta', '#', 1, 2) -1) from dual;
--제4 서브스트링
select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 3)+1) from dual;
안부 전합니다
이매뉴얼
function numinstr(p_source in varchar2,p_token in varchar2)
return pls_integer
is
v_occurrence pls_integer := 1;
v_start pls_integer := 1;
v_loc pls_integer;
begin
v_loc:=instr(p_source, p_token, 1, 1);
while v_loc > 0 loop
v_occurrence := v_occurrence+1;
v_start:=v_loc+1;
v_loc:=instr(p_source, p_token, v_start, 1);
end loop;
return v_occurrence-1;
end numinstr;
--
--
--
--
function get_split_field(p_source in varchar2,p_delim in varchar2,nth pls_integer)
return varchar2
is
v_num_delims pls_integer;
first_pos pls_integer;
final_pos pls_integer;
len_delim pls_integer := length(p_delim);
ret_len pls_integer;
begin
v_num_delims := numinstr(p_source,p_delim);
if nth < 1 or nth > v_num_delims+1 then
return null;
else
if nth = 1 then
first_pos := 1;
else
first_pos := instr(p_source, p_delim, 1, nth-1) + len_delim;
end if;
if nth > v_num_delims then
final_pos := length(p_source);
else
final_pos := instr(p_source, p_delim, 1, nth) - 1;
end if;
ret_len := (final_pos - first_pos) + 1;
return substr(p_source, first_pos, ret_len);
end if;
end get_split_field;
clob을 분할하여 sql에서 사용할 수 있는 함수가 필요했습니다.
create or replace type vchar_tab is table of varchar2(4000)
/
create or replace function split(
p_list in clob,
p_separator in varchar2 default '|'
) return vchar_tab pipelined is
C_SQL_VCHAR_MAX constant integer:=4000;
C_MAX_AMOUNT constant integer:=28000;
C_SEPARATOR_LEN constant integer:=length(p_separator);
l_amount integer:=C_MAX_AMOUNT;
l_offset integer:=1;
l_buffer varchar2(C_MAX_AMOUNT);
l_list varchar2(32767);
l_index integer;
begin
if p_list is not null then
loop
l_index:=instr(l_list, p_separator);
if l_index > C_SQL_VCHAR_MAX+1 then
raise_application_error(-20000, 'item is too large for sql varchar2: len='||(l_index-1));
elsif l_index > 0 then -- found an item, pipe it
pipe row (substr(l_list, 1, l_index-1));
l_list:=substr(l_list, l_index+C_SEPARATOR_LEN);
elsif length(l_list) > C_SQL_VCHAR_MAX then
raise_application_error(-20001, 'item is too large for sql varchar2: length exceeds '||length(l_list));
elsif l_amount = C_MAX_AMOUNT then -- more to read from the clob
dbms_lob.read(p_list, l_amount, l_offset, l_buffer);
l_list:=l_list||l_buffer;
else -- read through the whole clob
if length(l_list) > 0 then
pipe row (l_list);
end if;
exit;
end if;
end loop;
end if;
return;
exception
when no_data_needed then -- this happens when you don't fetch all records
null;
end;
/
테스트:
select *
from table(split('ASDF|IUYT|KJHG|ASYD'));
Oracle에서는 아래 SQL에서 myString을 하위 문자열로 분할합니다.
WITH rws AS (
SELECT
'str1,STR2,stR3,StR4' myString
FROM
dual
) SELECT
regexp_substr(
myString,
'[^,]+',
1,
level
) value
FROM
rws
CONNECT BY
level <= length(myString) - length(
replace(
myString,
','
)
) + 1;
결과는 다음과 같습니다.
str1
STR2
stR3
StR4
그 꼭지점 유틸리티의 외관이 마음에 드네요.그러나 이 기능에 사용할 수 있는 표준 Oracle 함수(subStr 및 inStr http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions001.htm)에 대해서도 알아두는 것이 좋습니다.
여러분, 간단한 방법이 있습니다.REPLACE 기능을 사용합니다.다음은 IN 절에 전달할 준비가 된 쉼표로 구분된 문자열의 예입니다.
PL/SQL의 경우:
StatusString := REPLACE('Active,Completed', ',', ''',''');
SQL Plus의 경우:
Select REPLACE('Active,Completed', ',', ''',''') from dual;
언급URL : https://stackoverflow.com/questions/3710589/is-there-a-function-to-split-a-string-in-oracle-pl-sql
'programing' 카테고리의 다른 글
배열을 정렬하는 TypeScript (0) | 2023.03.12 |
---|---|
WooCommerce 4+에서 제품에 커스텀 재고 상태를 추가하는 방법 (0) | 2023.03.12 |
JavaScript에서 날짜 개체를 수신하기 위해 JSON을 구문 분석하는 방법은 무엇입니까? (0) | 2023.03.12 |
문서에서 일부 필드를 제외하는 방법 (0) | 2023.03.12 |
MongoDB :: Mongo ID는 컬렉션 전체에서 고유합니까? (0) | 2023.03.12 |