--将一行中用特定字符分割的字段,分成多行
with t1 as
(
select '张三' c1,'胸外科,皮肤科,骨科1,骨科2,骨科3,骨科4,骨科5,骨科6,骨科7,骨科8,骨科9,骨科10,骨科11,骨科12,骨科13,骨科14,骨科15,骨科16,骨科17' c2,date'2000-11-19' c3 from dual
union all
select '李四','胸外科',date'2001-01-04' from dual
union all
select '王五','妇产科,骨科',date'2001-01-08' from dual
)
select c1,
substr(','||c2||',',instr(','||c2,',',1,b.rn)+1,
instr(c2||',',',',1,b.rn)-instr(','||c2,',',1,b.rn)) c2,c3
from t1,
(select rownum rn from t1
connect BY ROWNUM<20 ) b
where length(c2)-length(replace(c2,','))+1>=b.rn
order by c1,b.rn
(select rownum rn from t1 connect BY ROWNUM<20) b-- 是为了生成一个1-19的序列,相当于19行
length(c2)-length(replace(c2,','))+1>=b.rn -- b.rn 是递增的, c2字段分割后的数组长度, t1的每一条记录和b表做乘积达到复制记录的目的,>=b.rn 是限制复制记录的条数为分割后的数组长度。
----
with t1 as
(
select '张三' c1,'胸外科,皮肤科,骨科1,骨科2,骨科3,骨科4,骨科5,骨科6,骨科7,骨科8,骨科9,骨科10,骨科11,骨科12,骨科13,骨科14,骨科15,骨科16,骨科17' c2,date'2000-11-19' c3 from dual
union all
select '李四','胸外科',date'2001-01-04' from dual
union all
select '王五','妇产科,骨科',date'2001-01-08' from dual
)
select DISTINCT c1
,c3
,REPLACE( -- 去除多余的【,】
regexp_substr(c2||',' ,'.*?'||'[,]' ,1 ,LEVEL) -- 截取 ,【科室】,
,',') "科室"
from t1
connect by level <= nvl(
length(regexp_replace(c2,'[^,]','')) + 1
,1)
order by c1;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
regexp_substr:5个参数
第一个是输入的字符串
第二个是正则表达式
第三个是标识从第几个字符开始正则表达式匹配。(默认为1)
第四个是标识第几个
匹配组。(默认为1)
第五个是是取值范围:
i:大小写不敏感;
c:大小写敏感;
n:点号 . 不匹配换行符号;
m:多行模式;
x:扩展模式,忽略正则表达式中的空白字符。
关于:.*? 正则表达式的贪婪匹配和惰性匹配
贪婪匹配(greedy):它会匹配尽可能多的字符。它首先看整个字符串,如果不匹配,对字符
串进行收缩;遇到可能匹配的文本,停止收缩,对文本进行扩展,当发现匹配的文本时,它
不着急将该匹配保存到匹配集合中,而是对文本继续扩展,直到无法继续匹配 或者 扩展完
整个字符串,然后将前面最后一个符合匹配的文本(也是最长的)保存起来到匹配集合中。所
以说它是贪婪的。
惰性匹配(lazy):它会匹配尽可能少的字符,它从第一个字符开始找起,一旦符合条件,立
刻保存到匹配集合中,然后继续进行查找。所以说它是懒惰的。
默认使用贪婪匹配,在次数限定元字符后加?转为惰性匹配
另附几个元字符的意义:
'^' 匹配输入字符串的开始位置,在方括号表达式中使用,此时它表示不接受该字符集合。
'$' 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或'\r'。
'.' 匹配除换行符 \n之外的任何单字符。
'?' 匹配前面的子表达式零次或一次。
'*' 匹配前面的子表达式零次或多次。
'+' 匹配前面的子表达式一次或多次。
'( )' 标记一个子表达式的开始和结束位置。
'[]' 标记一个中括号表达式。
'{m,n}' 一个精确地出现次数范围,m=<出现次数<=n,'{m}'表示出现m次,'{m,}'表示至少出现m次。
'|' 指明两项之间的一个选择。例子'^([a-z]+|[0-9]+)$'表示所有小写字母或数字组合成的字符串。
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。
正则表达式的一个很有用的特点是可以保存子表达式以后使用,被称为Backreferencing. 允许复杂的替换能力