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