上一篇我们讲到with语句可以实现 分层数据处理,深度优先搜索,这次来点新的介绍 递归子查询因子来分割数据字符串:

可以看到这里我们将4段语句依据24个字符为一行,用递归的方式进行拆分了,这就是with的强大之处,然而还不够!
当我们想要替换字符串中的若干个不固定的值时,我们不能使用单个替换语句,
无论是translate replace,比如正则表达式regexp_replace,因为每个都需要多个函数调用,彼此嵌套,每个都有单独的搜索条件和替换标准。
如果我们只想提供一个单一标准集,可以有效地循环该标准并执行多个替换。
虽然它仍然无法在单个函数调用中完成,但我们可以使用递归作为循环机制,允许我们只是提供一套替换标准 .

注意:regexp_replace执行并不是直接根据表数据进行操作,优先级是根据他前面操作的列来的(如果是同一个列的话)需要放在最上面select 列里面,如果顺序不同,结果也会截然不同:

当然,with功能不仅止于此,如果我们有一个二进制字符串,我们想得到该字符串的十六进制值(oracle已经提供了一种使用TO_CHAR对NUM进行十六进制的方法,但不是二进制值):
with hx(val, hx) as ( -- 二进制到十六进制的查找表-16位
select substr('0000000100100011010001010110011110001001101010111100110111101111'
,((level-1)*4)+1,4
) as val
,substr('0123456789ABCDEF',level,1) as hx
from dual
connect by level <= 16
),
bin as (select '10100101010100100101' as bin from dual) -- 输入二进制值
,hx2bin(bin, hx, final) as (
select bin, cast(null as varchar2(20)) as hx, 0 as final
from bin
union all
select substr(hx2bin.bin,1,length(hx2bin.bin)-4) as bin
,hx.hx||hx2bin.hx as hx
,case when length(hx2bin.bin) <= 4 then 1 else 0 end as final
from hx2bin join hx on (hx.val = lpad(substr(hx2bin.bin,-least(4,length(hx2bin.bin))) ,4,'0'))
)
select hx from hx2bin
where final = 1

这是从右侧一次取四个二进制数字并查找那些十六进制数字,构建十六进制值。但是,知道二进制只是2的倍数,我们可以使用TO_CHAR将数字转换为Hex,我们也可以这样做

但是,这受NUMBER数据类型可容纳的最大值的限制,而第一种方法仅受限制提供的二进制字符串的大小
通常sqlplus编写procedure,当not compile时候,我们通常通过show error方式可以看到报错信息内容,例如如下代码:


这里我们调用了一个我知道不存在的函数“FMOD”,其次,我在dbms_output行的字符串中转义我的引号,将 编译器的报错展示了出来。
好了放松结束,
我们把案例做个分解,带着疑问去编程,我们可以将其分解为由括号括号(括号)定义的组成部分吗?我们从一个递归子查询开始,该子查询解析字符串的“标记”(单个括号“(”和“)”,由周围大括号“{”和“}”定义的值/变量,以及运算符“&”和“||”),看上去不太好理解,来看代码:

看上去成功了,字符串被一个个剥离了,和我们预期的一样,注意再看下面的写法:

整个表达式分解为括号中定义的组件表达式。
级别1是整个表达式,级别2显示级别1中的每个表达式,级别3显示表达式,在任何2级表达内;
在这种情况下,“(({MAI}&{LI})”表达式位于“({DAI}||({MAI}&{LI}))”内。
请注意,在上面的递归子查询中,Anchor成员提供了几个起始行数据,即所有行,有一个左括号“(”。
这使它成为每个(子)表达式的开始,并通过计算开始和结束括号,因为它将数据连接在一起,它可以确定何时在右括号“) ”结束。
以上都是with使用递归子查询因子来处理字符串的案例,最后一篇我将会给大家介绍点更好玩的,敬请期待!





