oracle 10g中的正則表達式


Oracle 10g 的正則表達式是處理文本數據的一個強有力的工具, 正則表達式在許多程序
語言和Unix下已經使用很久了.
Oracle 通過在SQL函數或者WHERE子句中執行正則表達式, 如果你對正則表達式不熟悉,
這篇文章可以給你一個大概的介紹, 熟悉正則表達式的讀者可以瞭解怎麼在Oracle SQL語言中實現這個功能
  什麼是正則表達式?
  正則表達式由一個或多個字符和/或者字符元, 最簡單的形式由字符組成, 像正則表達式cat,
被解釋爲字符c後面跟着a和t, 這樣的模式匹配字符串有 cat, location 和catalog. 字符元爲Oracle怎麼處理

正則表達式提供了運算規則。 如果, 你瞭解了各種字符元的意思, 你就明白正則表達式在處理獨立和代替文本

字符方面是多麼的強大.
  數據有效性, 重複詞的辨認, 無關的空白檢測,或者分解多個正則組成的字符串, 可以用來檢查電話號碼

的有效性, 郵政編碼,E-mail地址, 社保號碼,IP地址, 文件名和路徑, 等等。甚至可以用來模式定位,

如HTML的標籤,數字, 日期,或者任何模式匹配的字符或者代替他們的模式
  在Oracle 10g中使用正則表達式

爲了控制正則表達式可以使用Oracle中新的REGEXP_LIKE, REGEXP_INSTR, 和REG_EXP_REPLACE 函數, 你將會

看到這些函數怎樣增強了LIKE, INSTR, SUBSTR和REPLACE函數的功能. 實際上,和已經存在的函數呵操作相似

,只是提供了強大的字符匹配能力。
   正則表達式簡單的例子
使用新功能之前, 要了解一些字符元的含義。句號(.)匹配正則表達式中的任一個字符(不包括新的一行). 例

如正則表達式a.b匹配一個包括a, 然後任意一個字符, 然後是b的字符串, 如字符串axb, xaybx, abba。 如

果要匹配以a開頭以b結尾的三個字符的字符串, 必須使用^字符元指定開始行, 以$符號結束, 因此, 正規表達

式^a.b$匹配的字符串如: aab, abb 或者axb, 就像LIKE 操作一樣 a_b一樣。
  默認的, 單個字符或者字符串列表再正則表達式中只匹配一次,如過要多次匹配,必須使用循環操作。 如果

你想匹配一個以a開頭, 以b結尾的字符串, 正則表達式爲:^a.*b$, *字符元重複.0次,1次或者多次。
表2列出了完全的重複操作。 如果在表達式重使用圓括號, 可以創建子表達式,被重複執行數次。 例如, 正

則表達式b(an)*a 可以匹配 ba, bana, banana, yourbananasplit, 等等
  Oracle正則表達式支持POSIX字符類,見表3。 那意味着你可以很精確的使用你想要的字符類型。 想象一下

爲一個不是按照字母順序的紀錄寫一個LIKE條件的查詢, WHERE條件很容易變得非常複雜
POSIX字符類必須以方括號結束([]), 例如正則表達式[[]]匹配一個小寫字符, [[]]{5}匹配5

個連續的小寫字符
  除了POSIX字符類以外, 還可以在字符列中放置單獨的字符, 例如正則表達式^ab[cd]ef$匹配字符串abcef

和abdef, 字符c或者d必須被選中.
大部分字符串列表中的字符元從字面上解釋, 除了字符"^"和"-". 正則表達式看起來很複雜是由於有些字符元

有多種意思, 這取決於上下文, "^"就是這樣的一個字符元. 如果"^"是字符列中的第一個字符,就表示對這個

字符串取反,因此, [^[]]就是表示查找不包含數字的模式, ^[[]]匹配以數字開頭的字符串.

字符"-"表示一個範圍,正則表達式[a-m]匹配從a到m的字母, 但是如果字符"-"在開頭,就表示一個連字符,

如[-afg].
  前面的一個例子介紹了用圓括號創建子表達式, 可以用豎線(|)進入循環交替. 例如, 正則表達式t(a|e|i)n

允許t與n中的三個字符可以任選一個, 匹配的字符串例如tan, tin, 和Pakistan, 但不包括teen, mountain或

者tune. 作爲可選擇的,
表達式t(a|e|i)n 也可以被理解爲字符列t[aei]n. 表4列出了這些字符元。
  REGEXP_LIKE 操作
    下面的SQL查詢中WHERE從句顯示了怎麼使用REGEXP_LIKE函數, 在ZIP列中查詢滿足正則表達式

[^[]]的模式。 查詢返回ZIPCODE表中包含字符不全是數字的行:
SELECT zip
  FROM zipcode
WHERE REGEXP_LIKE(zip, '[^[]]')
ZIP
-----
ab123
123xy
007ab
abcxy

這個例子中正則表達式只是由字符元組成, 更多明確的數字字符類用冒號和方括號標示. 第二組括號嵌套了一

個字符類列表,就像前面說的,這是個必不可少的, 你可以用POSIX字符類來創建字符列表
  REGEXP_INSTR函數
這個函數返回模式的開始位置, 有點像INSTR函數, 語法見表6,兩個函數不同之處是REGECP_INSTR可以讓你指

定一個模式而不是特定的查找字符串,這樣就提供了強大的功能, 下面的例子使用REGEXP_INSTR返回字符串

"Joe Smith, 10045 Berry Lane, San Joseph, CA 91234"中5個郵政編碼的開始位置,如果正則表達式寫成

[[]]{5}, 得到的將是門牌號而不是郵編, 因爲10045是第一個以5個數字出現的模式, 因此必須用字符

元"$"表明是最後一個,  這個函數將返回郵編的開始位置而不管門牌號:
SELECT REGEXP_INSTR('Joe Smith, 10045 Berry Lane, San Joseph, CA 91234',
       '[[]]{5}$')
       AS rx_instr
  FROM dual
  RX_INSTR
----------
        45

寫一些複雜的模式
我們擴展一下前面郵政編碼的模式匹配, 包括一個可選的4個數字,正則表達式爲: 

[[]]{5}(-[[]]{4})?$. 如果你的源字符串以5個數字的郵編代碼或者5個數字的郵編+4個數字的

郵編組成, 這個正則表達式可以用來找到開始位置
SELECT REGEXP_INSTR('Joe Smith, 10045 Berry Lane, San Joseph, CA 91234-1234',
       ' [[]]{5}(-[[]]{4})?$')
    AS starts_at
  FROM dual
STARTS_AT
----------        44
這個例子中括號內的表達式(-[[]]{4}) 被重複0次或者1次, 由"?"循環操作控制。如果試圖用傳統的

SQL函數取得這樣的結果對SQL專家來說都是很困難的。 要想對正則表達式的各種變量有個瞭解, 參見表7.
  REGEXP_SUBSTR 函數
和SUBSTR函數差不多, 分解出字符串的一部分, 表8列出了這個函數的用法。 下面的例子中,返回匹配模式",

[^,]*,"的字符串,正則表達式查找逗號後面跟一個空格,後面跟着非","的字符或者字符串, 最後以逗號結束


SELECT REGEXP_SUBSTR('first field, second field , third field',
       ', [^,]*,')
  FROM dual
REGEXP_SUBSTR('FIR
------------------
, second field   ,

REGEXP_REPLACE 函數
傳統的REPLACE函數, 用一個字符串代替另一個, 假設你的數據裏面有很多的空白字符要用一個空白字符替換

, 用REPLACE函數的話, 必須指出替換多少個空白字符。  下面的例子中在Joe和Smith中間有3個空白,

REPLACE函數的參數指定用一個空白字符替換兩個空白字符, 這樣就把原來的一個沒有替換
SELECT REPLACE('Joe   Smith','  ', ' ')
       AS replace
  FROM dual
REPLACE
---------
Joe Smith
REGEXP_RELPLACE 函數會好一些, 語法在表9中列出。 下面的例子用一個空格替換兩個或者多個空格。 ()子

表達式包含一個空格, 可以重複一次或者多次, 由{2,}指示.

SELECT REGEXP_REPLACE('Joe   Smith',
       '( ){2,}', ' ')
       AS RX_REPLACE
  FROM dual
RX_REPLACE
----------
Joe Smith

    Backreference

正則表達式的一個很有用的特點是可以保存子表達式以後使用, 被稱爲Backreferencing(在表10中彙總). 允

許複雜的替換能力如調整一個模式到新的位置或者指示被代替的字符或者單詞的位置. 被匹配的子表達式存儲

在臨時緩衝區中, 緩衝區從左到右編號, 通過\數字符號訪問。
下面的例子列出了把名字 ELLen Hildi Smith 變成Smith, Ellen Hildi.
SELECT REGEXP_REPLACE(
       'Ellen Hildi Smith',
       '(.*) (.*) (.*)', '\3, \1 \2')
  FROM dual
REGEXP_REPLACE('EL
------------------
Smith, Ellen Hildi

這個SQL語句顯示了3個獨立的以圓括號表示的子表達式, 每個子表達式匹配任意一個字符元, 圓括號創建的子

表達式獲得的值以\數字參考, 第一個子表達式被賦予\1, 第二個被賦予\2...等等. Backreference在最後一

個參數中使用, 有效的返回了替換字符串的格式(包括逗號和空格). 表11列出了這種正則表達式的各個組成部


  Backreference 替換, 格式化, 取值方面很有用的. 下面的例子用REGEXP_SUBSTR函數來查找重複出現的以

空格分開的詞。 顯示的結果指出重複的子串。

SELECT REGEXP_SUBSTR(
       'The final test is is the implementation',
       '([[]]+)([[]]+)\1') AS substr
  FROM dual
SUBSTR
------
is is

   匹配參數選項

你可能已經注意到了正則表達式操作和函數包含了一個可選的匹配參數. 這個參數可以控制大小寫, 匹配新一

行的字符, 合併多行輸入。

   正則表達式的實踐應用
正則表達式不僅可以用在查詢中, 還可以用在任何可以使用SQL操作或者函數的地方,例如PL/SQL語言中. 可

以在觸發器中利用正則表達式的功能來檢查數據有效性, 產生, 或者提取數值。
下面的例子演示了怎麼用REGEXP_LIKE 操作再列中檢查數據約束的有效性. 在insert或者update的時候檢查社

保號碼的正確格式. 社保號的格式像123-45-6789, 123456789, 有效的數字必須以3個數字開頭, 跟着一個連字

符, 兩個數字, 一個連字符, 最後是4個數字。 交替出現的表達式只能出現9個數字, 豎線分開每個單獨的

選擇.
ALTER TABLE students
  ADD CONSTRAINT stud_ssn_ck CHECK
  (REGEXP_LIKE(ssn,
  '^([[]]{3}-[[]]{2}-[[]]{4}|[[]]{9})$'))
以字符開始或者結尾都是不允許的,這個由"^"和"$."可以看出。 必須注意正則表達式不能被分開成多行或者

有空格. 表12解釋了正則表達式單獨組成部分的例子。
參見10g的主頁/products/database/oracle10g/index.html

   正則表達式和其他已經存在的函數的比較

正則表達式比一般的LIKE, INSTR, SUBSTR和REPLACE函數有很多好處, 傳統的SQL函數沒有方便的模式匹配功

能, 雖然通過使用"%"和"_", LIKE操作可以匹配字符串, 但LIKE不能支持重複的表達式, 複雜的交替, 字符

範圍, 字符列, POSIX字符類等等. 此外, 新的正則表達式可以檢測重複詞和交換匹配模式的位置, 上面的

例子可以大概看出怎麼在應用中使用正則表達式


非常穩固的與你的工具包結合


正則表達式是很有用的, 可以幫助你解決複雜的問題。 一些正則表達式的功能用傳統的SQL函數很難表達出來

。 當你學會了這個祕密語言之後, 正則表達式將會成爲你的工具包裏不可缺少的一部分, 不僅僅是SQL, 還

包括其他的程序語言,雖然有時候要經過反覆試驗你的模式才能正確, 正則式的功能是顯而易見的.



Alice Rischert ([email protected]) chairs the Database Application Development and Design track at

Columbia University's Computer Technology and Application Program. She is the author of the

Oracle SQL Interactive Workbook 2nd edition (Prentice Hall, 2002) and the forthcoming Oracle SQL

by Example (Prentice Hall, 2003). Rischert has over 15 years of experience as a database

architect, DBA, and project leader for Fortune 100 companies and she has worked with Oracle since
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章