如何使用正则表达式检查字符串是否与Oracle中的多个条件匹配?

时间:2015-12-31 09:56:20

标签: regex oracle oracle10g

在与正则表达式斗争之后,我提出了与此类词匹配的^(ABC_)\w*(_USER[0-9]*)\w*(_MOD_)\w*模式

如果字符串以ABC_开头且包含_USER with any number following it,并且之后还包含单词_MOD_

匹配字符串的示例:

ABC_sssss_USER0000000000_sssss_MOD_sssss

ABC_SCssB_USER0332_MOD_REG_SP

在此工具中测试: http://www.regexpal.com/

但是我无法在oracle sql中使用它

以下是我的测试代码:

SELECT
    OBJECT_NAME,
    REGEXP_INSTR(OBJECT_NAME, '^(ABC_)\w*(_USER[0-9]*)\w*(_MOD_)\w*') AS IS_MATCH
FROM
    (

        SELECT 'ABC_SCssB_USER0332_MOD_REG_SP' OBJECT_NAME FROM DUAL UNION
        SELECT 'ABC_SCssB_USER0332_REG_SP' FROM DUAL UNION
        SELECT 'SCssB_USER0332_MOD_REG_SP' FROM DUAL UNION
        SELECT 'ABC_SCssB_MOD_REG_SP' FROM DUAL
    )

结果:

ABC_SCssB_MOD_REG_SP            0
ABC_SCssB_USER0332_MOD_REG_SP   0
ABC_SCssB_USER0332_REG_SP       0
SCssB_USER0332_MOD_REG_SP       0

预期结果:

ABC_SCssB_MOD_REG_SP            0
ABC_SCssB_USER0332_MOD_REG_SP   1
ABC_SCssB_USER0332_REG_SP       0
SCssB_USER0332_MOD_REG_SP       0

我如何在oracle中实现这一目标?

2 个答案:

答案 0 :(得分:2)

如果未强制使用正则表达式,则可以执行此操作,假设在' _USER'之后需要一个或多个数字:

select
    object_name,
    case when translate(OBJECT_NAME, '#0123456789', ' ##########') 
              like 'ABC\_%\_USER#%\_MOD\_%' escape '\' 
         then 1 
         else 0 
         end as is_match
from
    (
        select 'ABC_SCssB_USER0332_MOD_REG_SP' object_name from dual union
        select 'ABC_SCssB_USER0332_REG_SP' from dual union
        select 'SCssB_USER0332_MOD_REG_SP' from dual union
        select 'ABC_SCssB_MOD_REG_SP' from dual
    );

这比我的regexp版本(在12.1.0.1.0上)运行得快一点 - 大约75%的正则表达式版本花费的时间。

如果' _USER'之后可以有0位或更多位数字。那么这样做:

select
    object_name,
    case when OBJECT_NAME like 'ABC\_%\_USER%\_MOD\_%' escape '\'
         then 1
         else 0
         end as is_match
from
    (
        select 'ABC_SCssB_USER0332_MOD_REG_SP' object_name from dual union
        select 'ABC_SCssB_USER0332_REG_SP' from dual union
        select 'SCssB_USER0332_MOD_REG_SP' from dual union
        select 'ABC_SCssB_MOD_REG_SP' from dual
    );

答案 1 :(得分:1)

好的,如果您将\w*更改为.*,结果会有效。但是,仍然不清楚导致\w失败的原因。

我曾经在字符类中遇到非拉丁范围(如[A-z],但对于西里尔语,[А-я])因NLS_SORT设置而无法正常工作。也许类似的东西正在影响\w

@simsim,请发布您的确切数据库版本和NLS设置,以便我们可以尝试找到问题的根源,并使这个问题对其他人更有用。

修改

结果原因简单得多 - 数据库版本10.1是罪魁祸首,正则表达式支持仅在10g中添加,而\w在此版本中根本不受支持。我的实例是10.2和“受perl影响的扩展程序”were only added in 10.2 - 请参阅this table以获取已添加内容的完整列表,并this link查看10.1中可用的内容。请注意,您也不支持非贪婪量词(.*?.+?)或类似\d等字符类。