以 ABBA 结尾的 Oracle 正则表达式匹配模式

Oracle regex match pattern ending with ABBA

我希望能够找到以模式“ABBA”结尾的字符串,其中 A - 数字 B - 数字,不等于 A.

考虑一个与上述模式匹配的字符串 - 88889889。通常,我会在其他语言中使用负面前瞻,如下所示

但是 Oracle 不支持否定前瞻。这在 Oracle 中如何实现? 甲骨文版本: Oracle Database 19c 企业版 Release 19.0.0.0.0

我试过这样实现:

select 1 "val"
 from dual
where regexp_like('88889889','\S+(\d)(\d)$');

但是,它同时匹配 88889889 和 88889999。

如果它 不必 是正则表达式,相当简单的条件 substr 就可以完成工作:

示例数据:

SQL> with test (col) as
  2    (select 88889889 from dual union all  -- valid
  3     select 12345432 from dual union all  -- invalid
  4     select 443223   from dual union all  -- valid
  5     select 1221     from dual            -- valid
  6    ),

为了简单起见,提取最后 4 位数字(当然,您会丢弃所有短于 4 位数字的值,对吗?):

  7  temp as
  8    (select col, substr(col, -4) last4
  9     from test
 10    )

最后:

 11  select col,
 12    case when substr(last4, 1, 1) = substr(last4, 4, 1) and
 13              substr(last4, 2, 1) = substr(last4, 3, 1) then 'valid'
 14         else 'invalid'
 15    end result
 16  from temp;

       COL RESULT
---------- -------
  88889889 valid
  12345432 invalid
    443223 valid
      1221 valid

SQL>

选项 1:

您可以比较捕获组值以确保它们不相等:

SELECT value,
       1 "val"
FROM   table_name
WHERE  REGEXP_SUBSTR(value,'\S+(\d)(\d)$', 1, 1, NULL, 1)
       <> REGEXP_SUBSTR(value,'\S+(\d)(\d)$', 1, 1, NULL, 2);

选项 2:

或者,使用简单(更快)的字符串函数:

SELECT value,
       1 "val"
FROM   table_name
WHERE  SUBSTR(value, -4, 1) = SUBSTR(value, -1, 1)
AND    SUBSTR(value, -3, 1) = SUBSTR(value, -2, 1)
AND    SUBSTR(value, -4, 1) <> SUBSTR(value, -3, 1);

选项 3:

或者,如果您在数据库中启用了 Java,那么您可以创建一个 Java 函数来匹配正则表达式:

CREATE AND COMPILE JAVA SOURCE NAMED RegexParser AS
import java.util.regex.Pattern;

public class RegexpMatch {
  public static int match(
    final String value,
    final String regex
  ){
    final Pattern pattern = Pattern.compile(regex);

    return pattern.matcher(value).matches() ? 1 : 0;
  }
}
/

然后将其包装在 SQL 函数中:

CREATE FUNCTION regexp_java_match(value IN VARCHAR2, regex IN VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA NAME 'RegexpMatch.match( java.lang.String, java.lang.String ) return int';
/

然后在SQL中使用:

SELECT value,
       1 "val"
FROM   table_name
WHERE  REGEXP_JAVA_MATCH(value,'\S+(\d)(?!)(\d)$') = 1;

其中,对于示例数据:

CREATE TABLE table_name (value) AS
SELECT '88889889' FROM DUAL UNION ALL
SELECT '88889999' FROM DUAL UNION ALL
SELECT '88881234' FROM DUAL;

所有三个选项输出:

VALUE val
88889889 1

db<>fiddle here