我的表“ COMMA_SEPERATED”看起来像这样
id | referrals
----------------------------------------
1 | [{"risk_score":"1"}]
2 | [{"risk_score":"2"}]
我想将每个城市分开作为新记录,所以我的SQL是:(工作正常)
ID NAME CITY
--- ---- -----------------------------
1 RAJ CHENNAI, HYDERABAD, JABALPUR
2 SAM BHOPAL,PUNE
我想将这段SQL转换为一个函数,以便我可以像这样简单地调用该函数
SELECT id, TRIM(CITY_NEW)
FROM COMMA_SEPERATED, xmltable
(
'if (contains($X,",")) then ora:tokenize($X,"\,") else $X'
passing city AS X
columns CITY_NEW varchar2(4000) path '.'
);
输出:
SELECT id, split_function(city) FROM COMMA_SEPERATED
有人可以帮忙吗?我是PL / SQL的新手。
答案 0 :(得分:1)
除了@Alex所显示的内容之外,您还可以创建一个object
并通过object
返回function
。见下文:
--Created an object to hold your result columns
create or replace type Obj IS OBJECT (id number, city varchar2(20));
/
--Table of object
create or replace type var_obj is table of Obj;
/
--Function with return as with Object type.
create or replace function splt_fnct
return var_obj
as
var var_obj:=var_obj();
begin
Select obj(col,col1)
bulk collect into var
from (
Select distinct col , regexp_substr(col1,'[^,]+',1,level) col1
from tbl
connect by regexp_substr(col1,'[^,]+',1,level) is not null
order by 1);
return var;
end;
/
--Selecting result
select * from table(splt_fnct);
编辑:我正在尝试@Alex解决方案,但出现如下所示的错误:
create or replace function splt_fnct(input_strng varchar2)
return var_obj
as
var var_obj:=var_obj();
begin
Select obj(col,col1)
bulk collect into var
from (
select tbl.col, t.rslt --<--This column name should the same as used in colmns clause in the below query. Its giving error "invalid column". How to handle this case.
FROM tbl, xmltable
(
'if (contains($X,",")) then ora:tokenize($X,"\,") else $X'
passing col1 AS X
columns input_strng varchar2(4000) path '.'
) t
);
return var;
end;
/
根据@Alex建议进行更正:
create or replace function splt_fnct(input_strng varchar2)
return var_obj
as
var var_obj:=var_obj();
begin
select obj(tbl.col, t.rslt)
bulk collect into var
FROM tbl, xmltable
(
'if (contains($X,",")) then ora:tokenize($X,"\,") else $X'
passing input_strng AS X
columns rslt varchar2(4000) path '.'
) t;
return var;
end;
/
答案 1 :(得分:1)
您要获取的查询:
SELECT id, split_function(city) FROM COMMA_SEPERATED
无效,因为您试图为每个源行返回多个行。不幸的是,您必须使它复杂一些。
如果目标是隐藏拆分机制,那么我能想到的最接近的方法是创建一个返回字符串集合的函数,该字符串可以是pipelined:
create or replace function split_function (p_string varchar2)
return sys.odcivarchar2list pipelined as
begin
for r in (
select result
from xmltable (
'if (contains($X,",")) then ora:tokenize($X,"\,") else $X'
passing p_string as x
columns result varchar2(4000) path '.'
)
)
loop
pipe row (trim(r.result));
end loop;
end split_function;
/
您建议的通话将为您提供每个ID包含集合的一行:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
这不是您想要的;但是您可以使用表集合表达式和交叉联接将其转换为多行:
select cs.id, t.column_value as city
from comma_seperated cs
cross join table(split_function(cs.city)) t;
ID CITY
---------- ------------------------------
1 CHENNAI
1 HYDERABAD
1 JABALPUR
2 BHOPAL
2 PUNE
这并不像您希望的那样简单,但是可以说它比交叉连接到xmltable()
还要好,特别是如果您想在多个地方重用该拆分逻辑/功能以及隐藏拆分方式的详细信息-如果您愿意,可以轻松更改机制,例如使用更常见的正则表达式进行拆分。