在PL-SQL Oracle Apex中使用REGEXP进行许可证检查

时间:2016-11-04 12:47:21

标签: sql regex oracle plsql

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合作过,所以不知道如何使用它。

希望它清楚。

4 个答案:

答案 0 :(得分:2)

这可能是一种方法:

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检查所有的情况,使它更清晰。

答案 1 :(得分:1)

您可以使用标准字符串函数(而不是regexp)执行此操作,这样可以提高性能 - 如果需要考虑的话。

要测试是否存在字符,可以使用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 ...子句中单独使用这些测试。

答案 2 :(得分:0)

重要的是要意识到Oracle支持POSIX Extended Regular Expressions,这比你找到大多数地方的PCRE Regex都要受限制。

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

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

检查是否有两个字母(牌照中的任何位置)。

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

检查是否有两个号码。

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

要检查是否有元音,我会将NOT REGEX_LIKE()用于此正则表达式:

[AEIOU]

检查牌照是否包含从字符串的开头(^)到结尾($)的6个数字或字母。如果有任何其他字符或不同于6的字符数,则会失败。

答案 3 :(得分:0)

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

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

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

我认为这可以帮到你。

SUCCES !! Groet