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 的条件吗