Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Oracle SQL中的正则表达式模式替换文本字段字符串的一部分_Sql_Regex_Oracle - Fatal编程技术网

用Oracle SQL中的正则表达式模式替换文本字段字符串的一部分

用Oracle SQL中的正则表达式模式替换文本字段字符串的一部分,sql,regex,oracle,Sql,Regex,Oracle,我需要更新Oracle DB列上的一个(长)JSON字符串。我很幸运,更新只会在相对有限的行数(~50)上进行,因此性能不是最重要的。然而,和往常一样,我们也不希望它特别低效 更新查询的目标是查找并修改JSON中的字段: ... "myField":{"$bigdec":"1.23"} ... 我需要取出1.23,将其转换为(十进制)数字,对其应用公式并将结果放回 是否有任何内置的Oracle函数允许我查找表达式并对其进行修改?我脑子里想的唯一办法就是找到1.23开头和结尾的索引I和j,然后

我需要更新Oracle DB列上的一个(长)JSON字符串。我很幸运,更新只会在相对有限的行数(~50)上进行,因此性能不是最重要的。然而,和往常一样,我们也不希望它特别低效

更新查询的目标是查找并修改JSON中的字段:

... "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中解决。我发布这个解决方案只是为了炫耀(呃……我不应该承认这一点;让我们说“我把它作为我自己的良好实践,用于我自己的学习”)-你应该将其作为最后手段,而不是第一手段。