用Oracle SQL中的正则表达式模式替换文本字段字符串的一部分
我需要更新Oracle DB列上的一个(长)JSON字符串。我很幸运,更新只会在相对有限的行数(~50)上进行,因此性能不是最重要的。然而,和往常一样,我们也不希望它特别低效 更新查询的目标是查找并修改JSON中的字段:用Oracle SQL中的正则表达式模式替换文本字段字符串的一部分,sql,regex,oracle,Sql,Regex,Oracle,我需要更新Oracle DB列上的一个(长)JSON字符串。我很幸运,更新只会在相对有限的行数(~50)上进行,因此性能不是最重要的。然而,和往常一样,我们也不希望它特别低效 更新查询的目标是查找并修改JSON中的字段: ... "myField":{"$bigdec":"1.23"} ... 我需要取出1.23,将其转换为(十进制)数字,对其应用公式并将结果放回 是否有任何内置的Oracle函数允许我查找表达式并对其进行修改?我脑子里想的唯一办法就是找到1.23开头和结尾的索引I和j,然后
... "myField":{"$bigdec":"1.23"} ...
我需要取出1.23
,将其转换为(十进制)数字,对其应用公式并将结果放回
是否有任何内置的Oracle函数允许我查找表达式并对其进行修改?我脑子里想的唯一办法就是找到1.23开头和结尾的索引I
和j
,然后
SUBSTR(json, 1, i-2) || newNumber || SUBSTR(json, j+1)
理想情况下,我想做的最后一件事就是像我刚才做的那样处理I和j索引,并运行几个SUBSTR
调用,等等
还有比这更好的吗?
感谢您可以使用REGEXP_REPLACE函数来替换(顾名思义)允许正则表达式替换的函数(示例取出前3个字符,如果需要,将它们放在group1的新数字中)
update TABLENAME
set json = REGEXP_REPLACE(json, '^(...)', 'before\1afteroldnumber)
或者只是
update TABLENAME
set json = REGEXP_REPLACE(json, '1.23', 'newNumber')
还有“全局”的修饰符,例如,上面的示例将只交换第一次出现的情况。最好先测试:
select json, REGEXP_REPLACE...
以下是一些可能有效的方法:
with
inputs ( seq, str ) as (
select 1, 'alpha:"123.k"..."myField":{"$bigdec":"1.23"} and others'
from dual
),
nbr ( seq, n ) as (
select seq,
regexp_substr(str, '"myField":{"\$bigdec":"(\d+\.?\d*)"}', 1, 1, null, 1)
from inputs
),
repl ( seq, r_str ) as (
select seq, to_char( round(power(to_number(n), 3), 2), 'fm99999999.99')
from nbr
)
select i.seq, i.str,
regexp_replace(i.str, '"myField":{"\$bigdec":"\d+\.\d*"}',
'"myField":{"\$bigdec":"' || r.r_str || '"}') as repl_str
from inputs i inner join repl r on i.seq = r.seq
;
SEQ STR
---- ---------------------------------------------------------
1 alpha:"123.k"..."myField":{"$bigdec":"1.23"} and others
REPL_STR
--------------------------------------------------------
alpha:"123.k"..."myField":{"\$bigdec":"1.86"} and others
在这里,我取1.23,将其转换为一个数字,将其提高到三次方,将结果四舍五入到小数点后两位,转换为字符串(注意格式模型中的fm,没有它,您将得到一个额外的空间-作为符号的占位符,+或-),并在输入字符串中替换
序列号及其末尾的内部联接需要使每个输入字符串保持独立;如果您的输入表中还没有唯一的列(可用于此目的),则需要先创建一个列。另外,请密切注意$,我需要使用\来转义$(如果你知道要找什么,你会很容易看到它,但如果我没有提醒你,你可能会错过它)
祝你好运!可以有多个
“myField”:{“$bigdec”:“1.23”}
在专栏中?@vkp:好问题。我认为我们很幸运,不会发生这种情况。但这实际上是我接下来要问的第二个问题——如何处理这种特殊情况。多长是多长?它总是不超过4k个字符,还是CLOB专栏?@OmnowneDelysium——你可以轻松回答vkp的问题,只需运行一个regexp\u计数(…,pattern),并查看是否有返回值大于1的行。不应使用regex解析和修改json blob。请正确操作(不在DB中)。这不允许我对\1进行操作,或者会吗?如上所述,我需要对\1应用一个公式。尽管如此,我100%同意@alfasin:这个问题不应该在DB中解决。我发布这个解决方案只是为了炫耀(呃……我不应该承认这一点;让我们说“我把它作为我自己的良好实践,用于我自己的学习”)-你应该将其作为最后手段,而不是第一手段。