【问题标题】:License check with REGEXP in PL-SQL Oracle Apex在 PL-SQL Oracle Apex 中使用 REGEXP 进行许可证检查
【发布时间】:2017-03-18 07:28:56
【问题描述】:
create or replace trigger "KENTEKEN_CHECK"
after insert or update of kenteken
on auto
for each row

declare

kenteken varchar2;
teller number := 0;
tellerletter number := 0;
tellercijfer number := 0;

begin

kenteken := lower(:NEW.kenteken);

loop

if substr(kenteken, teller, 1) = REGEXP ("[eoiau]")  then
raise_application_error (-20502, 'Kenteken kan geen klinkers bevatten.');

elsif substr(kenteken, teller, 1) = REGEXP ("[0987654321]") then
tellercijfer := tellercijfer + 1;

elsif substr(kenteken, teller, 1) = REGEXP ("[qwrtypsdfghjklzxcvbnm]") then
tellerletter := tellerletter + 1;

else raise_application_error (-20502, 'Er is een ongeldig kenteken ingevoerd.');
end if;

teller := teller + 1;

exit when teller = 5;
end loop;

end;

我需要检查车牌(有六个字符)。它至少需要 2 个字母和 2 个数字,并且不允许使用 e、a、o、u 和 i。我应该如何使用REGEXP 正确的方法来检查这个?

  • Teller代表计数器
  • Tellernumber 代表数字计数器
  • Tellerletter 代表字母计数器

是的,我是这方面的初学者,所以不要责怪我的编码风格......以前从未使用过REGEXP,所以不知道如何使用它。

希望很清楚。

【问题讨论】:

  • 字母和数字有什么规律吗?像2个数字然后2个数字..等等
  • 我总是使用网站regexr.com 来检查我的正则表达式。
  • 欢迎来到 SO。尝试编辑您的问题,添加一些示例数据和所需的结果。如果你需要检查一个字符串,而不是编辑它,你可能需要 regexp_like
  • REGEXP ("[eoiau]") 不能在车牌中,REGEXP ("[0987654321]") 至少 2 个应该在车牌中,还有 REGEXP ("[qwrtypsdfghjklzxcvbnm ]") 至少 2
  • 但我想知道这些正则表达式的使用方式是否正确

标签: sql regex oracle plsql


【解决方案1】:
([qwrtypsdfghjklzxcvbnm]{2}\d{2}) ==> dd02

(\d{2}[qwrtypsdfghjklzxcvbnm]{2})  ==> 02dd

([qwrtypsdfghjklzxcvbnm]{2}-\d{2})  ==> dd-02

我认为这会完成你的工作。

成功了!! 格鲁特

【讨论】:

    【解决方案2】:

    您可以使用标准字符串函数(而不是正则表达式)来执行此操作,这应该会提高性能 - 如果这是一个考虑因素的话。

    要测试一个字符是否存在,您可以使用 TRANSLATE 从字符串中删除该字符,然后将结果字符串的长度与原始字符串的长度进行比较。您需要一个小技巧 - TRANSLATE 将从 FROM 列表中删除(删除)在 TO 列表中没有对应方的字符,但您不能有一个空的 TO 列表(如果这样做,结果将是 NULL字符串)。

    所以,是这样的:

    with test( s ) as (
           select 'axx11a' from dual union all
           select 'xxxx1x' from dual union all
           select '111111' from dual union all
           select 'xx1111' from dual union all
           select 'x1x1x1' from dual
         )
    -- end of test data; solution (SQL query) begins below this line
    select s
    from   test
    where length(translate(s, '~aeiou'                , '~'))  = length(s)
      and length(translate(s, '~0123456789'           , '~')) <= length(s) - 2
      and length(translate(s, '~qwrtypsdfghjklzxcvbnm', '~')) <= length(s) - 2
    ;
    
    S
    ------
    xx1111
    x1x1x1
    

    在您的程序中,您可以在 IF... 子句中单独使用这些测试。

    【讨论】:

      【解决方案3】:

      这可能是一种方法:

      with test(s) as (
          select 'axx11a' from dual union all
          select 'xxxx1x' from dual union all
          select '111111' from dual union all
          select 'xx1111' from dual union all
          select 'x1x1x1' from dual
      )
      select s
      from test
      where regexp_count(s, '[aeiou]') = 0
        and regexp_count(s, '[qwrtypsdfghjklzxcvbnm]') >= 2
        and regexp_count(s, '[0-9]') >= 2
      

      regexp_count统计字符串中正则表达式的出现次数;您可以使用它来检查给定集合中是否至少有 2 个字符,并检查是否没有不需要的字符。

      你可以用不同的方式重写这个,我用regexp_count检查了所有的情况,让它更清楚。

      【讨论】:

      • 好一个..可以再添加一个条件使总长度为 6。
      • 是的,非常感谢。这帮助了我。谢谢 Aleksej!
      【解决方案4】:

      意识到 Oracle 支持 POSIX Extended Regular Expressions 很重要,它比您在大多数地方找到的 PCRE 正则表达式更受限制。

      因为 POSIX ERE 不支持所谓的前瞻,所以我会使用这些正则表达式:

      .*[A-Z].*[A-Z]
      

      检查是否有两个字母(在车牌的任何地方)。

      .*[0-9].*[0-9]
      

      检查是否有两个数字。

      ^[A-Z0-9]{6}$
      

      要检查是否有元音,我会在这个正则表达式中使用NOT REGEX_LIKE()

      [AEIOU]
      

      检查车牌是否由字符串开头 (^) 到结尾 ($) 的 6 个数字或字母组成。如果有任何其他字符,或者不是正好 6 个字符,这将失败。

      【讨论】:

      • 如果车牌可能不包含 e o i u 怎么办?
      • @TomvR 添加了此要求。
      • 如果不能使用这 5 个字符,请使用 [^AEIOU]。
      • @wieseman 字符串 "DAF39F" 匹配 [^AEIOU] 5 次,更容易匹配 [AEIOU] 并在编程逻辑中说这种匹配可能不会发生。
      猜你喜欢
      • 2019-06-30
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多