LPAD和REGEXP_替换交互变得不可靠?

LPAD和REGEXP_替换交互变得不可靠?,regex,oracle,Regex,Oracle,这里有一些我无法解释的东西,希望能得到一些帮助,看看我明显遗漏了什么:) 在制定此问题的解决方案时: 我认为一个聪明的regexp_replace+LPAD会产生更好的排序值。然而,由于某种原因,LPAD一直表现不好。以下是简化测试中的“问题”: with w_data as ( select '9' v from dual union all select '18' v from dual ) select v, lpad(v,

这里有一些我无法解释的东西,希望能得到一些帮助,看看我明显遗漏了什么:)

在制定此问题的解决方案时:

我认为一个聪明的regexp_replace+LPAD会产生更好的排序值。然而,由于某种原因,LPAD一直表现不好。以下是简化测试中的“问题”:

  with w_data as (
     select '9'  v  from dual union all
     select '18' v  from dual
     )
  select v,
         lpad(v, 4, '0' ) a,
         regexp_replace(v, '([0-9]*)', lpad('\1', 4, '0')) b
  from w_data
  /

  V  
  -- 
  A
  ----
  B
  ----------
  9  
  0009
  00900

  18 
  0018
  001800


  2 rows selected.
如您所见,列“a”的行为与预期一致。。长度为4的字符串,左侧填充0

但是,一旦它通过regexp\u替换。。。它开始变得奇怪。。。为什么会这样? 如何将其与regexp\u replace“正确”结合使用? (请注意,我的正则表达式和字符串(根据链接的问题)稍微复杂一些;)

[编辑] 使用“[0-9]+”尝试。。但是仍然没有正确填充

  with w_data as (
     select '9'  v  from dual union all
     select '18' v  from dual
     )
  select v,
         lpad(v, 4, '0' ) a,
         regexp_replace(v, '([0-9]+)', lpad('\1', 4, '0')) b
  from w_data
  /

  V  
  -- 
  A
  ----
  B
  ----------
  9  
  0009
  009

  18 
  0018
  0018


  2 rows selected.

请注意,18正确显示(“0018”),但9仅显示为“009”3个字符?应该是四个:“0009”…

LPAD不理解正则表达式替换的特殊语法;这仅在直接传递给REGEXP函数时才有意义。所以这个表达式:

lpad('\1', 4, '0')

只是返回字符串“00\1”。然后将该字符串传递给REGEXP_REPLACE,它在正则表达式上下文中解释“\1”。

如果您确定所有数字都不超过4位,则可以使用以下方法:

with w_data as (
   select '9'  v  from dual union all
   select '18' v  from dual
   )
select v,
       REGEXP_REPLACE(
         REGEXP_REPLACE(v, '([0-9]+)', '000\1'),
         '(0*)([0-9]{4})', 
         '\2') b
from w_data
如果不是,这里有一个更复杂的解决方案:

with w_data as (
   select '9'  v  from dual union all
   select '18'  v  from dual union all
   select '123456' v  from dual
   )
select v,
       REGEXP_REPLACE(
         REGEXP_REPLACE(v, '([0-9]+)', '000\1'),
         '(0*)([1-9]?[0-9]{4})', 
         '\2') b
from w_data

我不明白你想要什么,你能把样品的格式改好吗。即使是OK,请参考另一个问题,您也应该始终在此处发布所有相关代码。你永远不知道是否有人删除了另一个问题请注意,
[0-9]*
可以在每个不匹配的序列/符号之前匹配一个空位置,我认为你需要
[0-9]+
。对不起。。意味着列“a”的行为正常。。。需要4个字符串的结果…@Stribizev:+更好。。但还是不完全。。让我更新它不可能在regexp\u replace的替换模式中传递反向引用。你需要找到另一种方法。啊。。。好吧,这是有道理的。。。O.O所以最好的“解决方法”可能是:
lpad(regexp\u replace(v),([0-9]+),'\1'),4,'0')
?我认为,regexp\u replace调用是无操作的。正则表达式的每个匹配项都将替换为自身。您是否试图从输入字符串中删除非数字字符?最终(根据另一个问题的链接),我尝试将9和18的字符串版本排序为“更好”,将它们转换为“0009”和“0018”。。正则表达式之所以出现,是因为它使用的是版本(如1.9、1.18等)因此,我试图将1.9转换为“0001.0009”(例如)。。。然后它会对“0001.0018”进行更好的排序。(我甚至知道正则表达式会给我带来麻烦:)所以我一直在寻找像这样的任务来学习/练习:)这太棒了。只是用同样的方法为MySQL/MariaDB创建了一个函数。太好了!我只需要写
\\1
而不是
\1
。我的数据库版本:
10.2.21-MariaDB-1:10.2.21+maria~bionic