以 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
我希望能够找到以模式“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