【问题标题】:Issue with replace function in OracleOracle中的替换功能问题
【发布时间】:2021-10-05 05:47:41
【问题描述】:

我想用 XXXXXX 替换字符串中最后 10 位数字中的 6 位。字符串的长度可以是 16 或 19。

使用以下查询:

SELECT REPLACE('0000000000000000000',SUBSTR('0000000000000000000',-10,6), 'XXXXXX') FROM DUAL;
--Actual Output  --XXXXXXXXXXXXXXXXXX0
--Expected Output--000000000XXXXXX0000

SELECT REPLACE('1234561234561234561',SUBSTR('1234561234561234561',-10,6), 'XXXXXX') FROM DUAL;
--Actual Output  --123XXXXXXXXXXXX4561
--Expected Output--123456123XXXXXX4561

SELECT REPLACE('0004421640006525212',SUBSTR('0004421640006525212',-10,6), 'XXXXXX') FROM DUAL;
--Actual Output  --000442164XXXXXX5212
--Expected Output--000442164XXXXXX5212

为什么前两个给出错误的结果,我该如何修复查询?

【问题讨论】:

标签: sql oracle replace oracle12c


【解决方案1】:

如果字符串的长度总是 19,你可以这样做:

substr('0004421640006525212', 1, 9) || 'XXXXXX' || substr('0004421640006525212', -4)

对于两种可能的长度,您可以使用 case 表达式根据实际字符串长度来决定第一个 substr() 调用的第二个参数;或者你可以允许任何长度(至少 10,无论如何):

substr('0004421640006525212', 1, length('0004421640006525212') - 10) || 'XXXXXX' || substr('0004421640006525212', -4)

或为简洁起见使用占位符/列:

substr(str, 1, length(str) - 10) || 'XXXXXX' || substr(str, -4)

或者可能更简单,但速度较慢,您可以使用正则表达式:

regexp_replace('0004421640006525212', '^(.*?)(.{6})(.{4})$', '\1XXXXXX\3')

正则表达式将字符串分成三组;向后工作,(.{4})$ 是字符串末尾的一组正好四个字符;然后(.{6}) 是一组正好六个字符(您要替换的字符);那么^(.*} 是字符串开头的任何/所有剩余字符的组。替换模式保留第一组和第三组 - 使用 \1\3 - 并在它们之间放置固定的 X。第二组 - 六个字符 - 被丢弃。

SQL Fiddle 获取值和几个较短的值,形成一个表格以避免必须全部重复;这也表明第一个版本在不同长度下无法正常工作。


replace 函数用一个字符串替换每个出现的字符串。它不知道也不关心第二个参数是如何生成的;它不知道您是从同一字符串中的特定位置获取它的。

当你这样做时:

REPLACE('0004421640006525212',SUBSTR('0004421640006525212',-10,6), 'XXXXXX')

SUBSTR() 的计算结果为 '000652',因此有效:

REPLACE('0004421640006525212','000652', 'XXXXXX')

这就是您想要的,因为该子字符串仅在原始字符串中出现一次。但是:

REPLACE('1234561234561234561',SUBSTR('1234561234561234561',-10,6), 'XXXXXX')

SUBSTR() 的计算结果为“456123”,因此它是有效的:

REPLACE('1234561234561234561','456123', 'XXXXXX')

并且在原始字符串中出现多次:

1234561234561234561
   ^^^^^^
         ^^^^^^

两者都被替换了。全为零的情况更糟; SUBSTR() 现在是 '000000',所以匹配了 3 次:

0000000000000000000
^^^^^^
      ^^^^^^
            ^^^^^^

这三个都被替换了。

【讨论】:

  • 谢谢亚历克斯。下面的查询解决了我的问题——regexp_replace('0004421640006525212', '^(.*?)(.{6})(.{4})$', '\1XXXXXX\3')。
  • 能解释一下正则表达式的逻辑吗?
  • @sonam - 我更新了答案,解释了正则表达式的作用。
猜你喜欢
  • 2013-05-18
  • 2017-06-05
  • 2021-12-31
  • 2016-04-12
  • 1970-01-01
  • 2018-08-19
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多