Oracle 10g正则表达式的使用总结

Oracle 10g数据库内建了符合IEEE POSIX (Portable Operating System for Unix)标准的正则表达式。熟练使用正则表达式,可以写出简洁,强大的SQL语句。
ORACLE中的支持正则表达式的函数主要有下面四个:
    1,REGEXP_LIKE :与LIKE的功能相似
    2,REGEXP_INSTR :与INSTR的功能相似
    3,REGEXP_SUBSTR :与SUBSTR的功能相似
    4,REGEXP_REPLACE :与REPLACE的功能相似
    这四个函数在用法上与Oracle SQL 函数LIKE、INSTR、SUBSTR 和REPLACE 用法相同,但是它们使用POSIX 正则表达式代替了老的百分号(%)和通配符(_)字符。

  POSIX 正则表达式由标准的元字符(metacharacters)所构成:
    '^' 匹配输入字符串的开始位置,在方括号表达式中使用,此时它表示不接受该字符集合。
  '$' 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'. '.' 匹配除换行符之外的任何单字符。
  '?' 匹配前面的子表达式零次或一次。
  '+' 匹配前面的子表达式一次或多次。
  '*' 匹配前面的子表达式零次或多次。
  '|' 指明两项之间的一个选择。例子'^([a-z]+|[0-9]+)$'表示所有小写字母或数字组合成的字符串。
  '( )' 标记一个子表达式的开始和结束位置。
  '[]' 标记一个中括号表达式。
  '{m,n}' 一个精确地出现次数范围,m=<出现次数<=n,'{m}'表示出现m次,'{m,}'表示至少出现m次。
  \num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。

  字符簇:
  [[:alpha:]] 任何字母。
  [[:digit:]] 任何数字。
  [[:alnum:]] 任何字母和数字。
  [[:space:]] 任何白字符。
  [[:upper:]] 任何大写字母。
  [[:lower:]] 任何小写字母。
  [[:punct:]] 任何标点符号。
  [[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F].

    各种操作符的运算优先级
    \转义符
    (), (?:), (?=), [] 圆括号和方括号
    *, +, ?, {n}, {n,}, {n,m} 限定符
    ^, $, anymetacharacter 位置和顺序。

下面收集了几个大家在Oracle SQL中常用到的正则表达式以及它们的用法,欢迎大家补充。
1. 判断字符串是否是数字
正则表达式:^(\-)?\d*(\.\d+)?$
用法:
select case when REGEXP_LIKE (cx.COMP_DATA_VALUE ,'^(\-)?\d*(\.\d+)?$')
                 then to_number(cx.COMP_DATA_VALUE)
                 else null
         end
  from change_on_setup.COMP_EXT cx
where cx.COMP_PLAN_ID = cp.COMP_PLAN_ID
    and cx.COMP_ENTRY_ID = ce.COMP_ENTRY_ID
    and cx.COMP_DATA_KEY = 'BUDGETSAL_A_D'

2. 判断字符串是否是日期
判断格式为mm/dd/yyyy的日期
正则表达式:^(((0?[1-9]|1[012])/(0?[1-9]|1\d|2[0-8])|(0?[13456789]|1[012]) /(29|30)|(0?[13578]|1[02])/31)/(19|[2-9]\d)\d{2}|0?2/29/((19|[2-9]\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00)))$

判断格式为dd/mm/yyyy的日期
正则表达式:^(((0?[1-9]|[012]\d|3[01])\/(0?[13578]|1[02])\/((19|[2-9]\d) \d{2}))|((0?[1-9]|[12]\d|30)\/(0?[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0?[1-9]|1\d|2[0-8])\/0?2\/((19|[2-9]\d)\d{2}))|(29\/0?2\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$

用法:
select case when REGEXP_LIKE(ui.USERS_VALUE, '^(((0?[1-9]|[012]\d|3[01])\/(0?[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0?[1-9]|[12]\d|30)\/(0?[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0?[1-9]|1\d|2[0-8])\/0?2\/((19|[2-9]\d)\d{2}))|(29\/0?2\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$')
                then to_char(to_date(ui.USERS_VALUE, 'dd/mm/yyyy'), 'dd/mm/yyyy')
                when REGEXP_LIKE(ui.USERS_VALUE, '^(((0?[1-9]|1[012])/(0?[1-9]|1\d|2[0-8])|(0?[13456789]|1[012])/(29|30)|(0?[13578]|1[02])/31)/(19|[2-9]\d)\d{2}|0?2/29/((19|[2-9]\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00)))$')
                then to_char(to_date(ui.USERS_VALUE, 'mm/dd/yyyy'), 'dd/mm/yyyy')
                else null
         end
  from change_on_setup.USERS_INFO ui
where ui.USERS_SYS_ID = u.USERS_SYS_ID
    and upper(ui.USERS_KEY) = 'REVIEW_FREQ'

3.去掉字符串中的除字母数字以外的任何字符
正则表达式:[^[:alnum:]]
用法:
下面的query将非英文字符的人名(比如Şağanaç, Çiçek)转换成英文人名(Saganac, Cicek)。其中用到了这个正则表达式去除转换后产生的特殊字符。
select upper(decode(instr(convert (replace(u.USERS_SYS_LASTNAME, '?'), 'us7ascii'), '?')
                            , 0, trim(regexp_replace(convert (u.USERS_SYS_LASTNAME, 'us7ascii'), '[^[:alnum:]]'))
                            , u.USERS_SYS_LASTNAME
                            )
              || ', ' ||
              decode(instr(convert (replace(u.USERS_SYS_FIRSTNAME, '?'), 'us7ascii'), '?')
                            , 0, trim(regexp_replace(convert (u.USERS_SYS_FIRSTNAME, 'us7ascii'), '[^[:alnum:]]'))
                            , u.USERS_SYS_FIRSTNAME
                            )
                    ) as "Name"
   from change_on_setup.USERS_SYSINFO u

另一种转换方法:
select regexp_replace (convert (users_sys_firstname||', '||users_sys_lastname, 'us7ascii'), '[[:punct:]]') as "Name"
  from change_on_setup.USERS_SYSINFO u

4. 将字符串拆分
正则表达式:
[^,]+
[^,]*
用法:
select TRIM(REGEXP_SUBSTR('cgrant,mhoff,vstokes','[^,]+', 1,level)) POS_CODE
  from dual
connect by level <= length(REGEXP_REPLACE('cgrant,mhoff,vstokes','[^,]*'))+1

输出结果:
USERNAME
--------
cgrant
mhoff
vstokes


更多的Oracle正则表达式可以参见这个网址(Alex推荐)
http://regexlib.com/

另外还有一个可以自动生成Oracle 10g正则表达式的工具——RegexBuddy
官方网站:http://www.regexbuddy.com/oracle.html

posted on 2013-01-15 15:09  Alice Sun  阅读(475)  评论(0编辑  收藏  举报

导航