PL/SQL:字符串的 regexp_like 不以字母开头

Posted

技术标签:

【中文标题】PL/SQL:字符串的 regexp_like 不以字母开头【英文标题】:PL/SQL: regexp_like for string not start with letters 【发布时间】:2013-12-19 17:32:09 【问题描述】:

用于在 Oracle 数据库 11g 上运行的 regexp_like。我想要一个模式来匹配一个不以 AM 或 AP 开头的字符串,该字符串通常是几个字母,后跟一个下划线和其他字母或下划线。 例如:

字符串:AM_HTCEVOBLKHS_BX [假] 字符串:AP_HTCEVOBLKHSPBX [假] 字符串:BM_HTCEVOBLKHS_BX [true] 字符串:A_HTCEVODSAP_DSSD [true] 字符串:A_HTCEVOB_A_CDSED [true] 字符串:MP_HTCEVOBLKHS_BX [true]

你能做这个图案吗?

我目前的解决方案不起作用:

BEGIN
    IF regexp_like('AM_HTCEVOBLKHS_BX','[^(AM)(AP)]+_.*') THEN
        dbms_output.put_line('TRUE');
    ELSE
        dbms_output.put_line('FALSE');
    END IF;
END;
/

【问题讨论】:

【参考方案1】:

为什么需要 regexp 为什么不使用简单的 substr?

with t1 as
 (select 'AM_HTCEVOBLKHS_BX' as f1
    from dual
  union all
  select 'AP_HTCEVOBLKHSPBX'
    from dual
  union all
  select 'BM_HTCEVOBLKHS_BX'
    from dual
  union all
  select 'A_HTCEVODSAP_DSSD'
    from dual
  union all
  select 'A_HTCEVOB_A_CDSED'
    from dual
  union all
  select 'MP_HTCEVOBLKHS_BX' from dual
  union all
  select null from dual
  union all
  select '1' from dual)

select f1,
       case
           when substr(f1, 1, 2) in ('AM', 'AP') then
            'false'
           else
            'true'
       end as check_result
  from t1

【讨论】:

对不起,我正在调用一个 API 过程,它需要传递一个正则表达式模式作为参数才能使其工作。而且已经定义了几十种其他模式,我不能对字符串进行硬编码,它是动态输入的。【参考方案2】:

如果你有一个模式表,那么:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE strings ( string ) AS
          SELECT 'AM_HTCEVOBLKHS_BX' FROM DUAL
UNION ALL SELECT 'AP_HTCEVOBLKHSPBX' FROM DUAL
UNION ALL SELECT 'BM_HTCEVOBLKHS_BX' FROM DUAL
UNION ALL SELECT 'A_HTCEVODSAP_DSSD' FROM DUAL
UNION ALL SELECT 'A_HTCEVOB_A_CDSED' FROM DUAL
UNION ALL SELECT 'MP_HTCEVOBLKHS_BX' FROM DUAL;

CREATE TABLE patterns ( pattern ) AS
          SELECT '^AM' FROM DUAL
UNION ALL SELECT '^AP' FROM DUAL;

查询 1

-- Negative Matches:
SELECT string
FROM   strings s
       LEFT OUTER JOIN
       patterns p
       ON ( REGEXP_LIKE( string, pattern ) )
WHERE  p.pattern IS NULL

Results

|            STRING |
|-------------------|
| BM_HTCEVOBLKHS_BX |
| A_HTCEVODSAP_DSSD |
| A_HTCEVOB_A_CDSED |
| MP_HTCEVOBLKHS_BX |

查询 2

-- Positive Matches:
SELECT DISTINCT
       string
FROM   strings s
       INNER JOIN
       patterns p
       ON ( REGEXP_LIKE( string, pattern ) )

Results

|            STRING |
|-------------------|
| AM_HTCEVOBLKHS_BX |
| AP_HTCEVOBLKHSPBX |

查询 3

-- All Matches:
SELECT string,
       CASE WHEN REGEXP_LIKE( string,
                              ( SELECT LISTAGG( pattern, '|' ) WITHIN GROUP ( ORDER BY NULL )
                                FROM   patterns )
                            )
            THEN 'True'
            ELSE 'False'
            END AS Matched
FROM   strings s

Results

|            STRING | MATCHED |
|-------------------|---------|
| AM_HTCEVOBLKHS_BX |    True |
| AP_HTCEVOBLKHSPBX |    True |
| BM_HTCEVOBLKHS_BX |   False |
| A_HTCEVODSAP_DSSD |   False |
| A_HTCEVOB_A_CDSED |   False |
| MP_HTCEVOBLKHS_BX |   False |

如果您想将模式作为单个字符串传递,那么:

查询 4

-- Negative Matches:
SELECT string
FROM   strings
WHERE  NOT REGEXP_LIKE( string, '^(AM|AP)' )

Results

|            STRING |
|-------------------|
| BM_HTCEVOBLKHS_BX |
| A_HTCEVODSAP_DSSD |
| A_HTCEVOB_A_CDSED |
| MP_HTCEVOBLKHS_BX |

查询 5

-- Positive Matches:
SELECT string
FROM   strings
WHERE  REGEXP_LIKE( string, '^(AM|AP)' )

Results

|            STRING |
|-------------------|
| AM_HTCEVOBLKHS_BX |
| AP_HTCEVOBLKHSPBX |

查询 6

-- All Matches:
SELECT string,
       CASE WHEN REGEXP_LIKE( string, '^(AM|AP)' )
            THEN 'True'
            ELSE 'False'
            END AS Matched
FROM   strings

Results

|            STRING | MATCHED |
|-------------------|---------|
| AM_HTCEVOBLKHS_BX |    True |
| AP_HTCEVOBLKHSPBX |    True |
| BM_HTCEVOBLKHS_BX |   False |
| A_HTCEVODSAP_DSSD |   False |
| A_HTCEVOB_A_CDSED |   False |
| MP_HTCEVOBLKHS_BX |   False |

【讨论】:

【参考方案3】:

试试这个:

^([B-Z][A-Z]*|A[A-LNOQ-Z]?|A[A-Z]2,)_[A-Z_]+$

这个想法是描述所有可能的字符串开头。

(                 # a group
    [B-Z][A-Z]*   # The first character is not a "A"
  |               # OR
    A[A-LNOQ-Z]?  # a single "A" or a "A" followed by a letter except "P" or "M"
  |               # OR
    A[A-Z]2,    # a "A" followed by more than 1 letter
)                 # close the group

^$ 是锚点,表示“字符串的开头”和“字符串的结尾”

【讨论】:

请问'?!' 是什么意思意思是?谢谢 @Frank:(?!..) 是一个否定的前瞻,意思是“不跟随”,但我已经删除了它,因为 PLSQL 似乎不支持这个功能。刷新你的页面。 它不起作用,我测试了 'D_HTCEVOBLKHS_BX' 'AD_HTCEVOBLKHS_BX' 应该返回 true,但两者都返回 false。【参考方案4】:

我认为你只需要这个:

not regexp_like( field, '^(AM_)|^(AP_)' )

由于它是 LIKE 函数,因此您不再需要正则表达式。

【讨论】:

以上是关于PL/SQL:字符串的 regexp_like 不以字母开头的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL。使用 regexp_like 正则表达式解析 clob UTF8 字符

我可以在 PL/SQL 块中使用 REGEXP_LIKE 作为 IF 的条件吗

pl/sql 正则表达式验证

SQL 基础正则表达式(二十三)

oracle通过添加regexp_like将字符串连接到数字不起作用

pl/sql 从数字到字符串的转换