內容提要
oracle 10g 增加的正則表達式函數有以下四種:
regexp_like() --返回滿足條件的字段
regexp_instr() --返回滿足條件的字符或字符串的位置
regexp_replace() --返回替換后的字符串
regexp_substr() --返回滿足條件的字符或字符串
這四個函數的功能分別對應傳統sql的 like操作符 和 instr 、replace 、substr函數,
在一般的、不怎么復雜的模式匹配中,使用傳統的sql函數就能滿足,當需要實現的操作
比較復雜時,使用正則表達式函數,就可以寫出簡潔、強大的sql語句。
匹配過程中可能會涉及到的元字符(Meta Character)對應的sql代碼:
^ 使表達式定位至一行的開頭
$ 使表達式定位至一行的末尾
* 匹配0次或更多次
? 匹配0次或1次
+ 匹配1次或更多次
{m} 正好匹配m次
{m,} 至少匹配m次
{m,n} 至少匹配m次但不超過n次
[:alpha:] 字母字符,匹配字符A-Z、a-z
[:lower:] 小寫字母字符,匹配字符a-z
[:upper:] 大寫字母字符,匹配字符A-Z
[:digit:] 數字,匹配數字0-9
[:alphanum:] 字母數字字符,匹配字符A-Z、a-z、0-9
[:space:] 空白字符(禁止打印),如回車、換行符、豎直制表符和換頁符[:punct:] 標點字符
[:cntrl:] 控制字符(禁止打印)
[:print:] 可打印字符|分隔替換選項,通常與分組符()一期使用
() 將子表達式分組為一個替換單元,量詞單元或后向引用單元
[char] 字符列表
. 匹配除null之外的任意單個字符
/ 要匹配的字符是一個特殊字符、常量或者后者引用
x|y 匹配 x 或 y
[abc] 匹配abc中的任何單個字符
[a-z] 匹配 a 到 z 范圍內的任意單個字符
以下為測試用例:
/*創建測試表==================================================================================*/
create table person
(
first_name varchar2(20),
last_name varchar2(20),
email varchar2(100),
zip varchar(6)
);
insert into person values('Steven','Chen','steven@hp.com','123456');
insert into person values('James','Li','jamesli@sum.com'||chr(10)||'lijames@oracle.com','1b3d5f');
insert into person values('Tina','Zhang','chillaxzx@163.com','2456hd');
insert into person values('Tom','Feng','Tomfeng@126.com','a654e5');
insert into person values('Jonson','zhao','Jonson@google.com','edjksk');
insert into person values('Vines','Wu','Vines@162.com','2djks4');
commit;
select * from person;
/*regexp_like()=================================================================================
regexp_like(search_string ,pattern[,match_option]);
參數說明:
search_string是搜索值
pattern 正則表達式元字符構成的匹配模式,長度限制在512字節內
match_option是一個文本串,允許用戶設置該函數的匹配行為。可以使用的選項有:
c 匹配時,大小寫敏感,默認值
i 匹配時,大小寫不敏感
n 允許使用原點(.)匹配任何新增字符
m 允許將源字符作為多個字符串對待
===============================================================================================*/
--zip字段以數字開始
select * from person where regexp_like(zip,'^[[:digit:]]');
--注意區別
select * from person where regexp_like(zip,'[^[:digit:]]'); --包含非數字
select * from person where regexp_like(zip,'[[:digit:]]'); --包含數字
--zip字段以數字結尾
select * from person where regexp_like(zip,'[[:digit:]]$');
--first_name字段以S開始,N結束的,不區分大小寫
select * from person where regexp_like(first_name,'^s.*N$','i'); --注意這里的'i'不能是‘I’,否則報錯
--email字段,注意區別
select email from person where regexp_like(email, '^james.*com$');
select email from person where regexp_like(email, '^james.*com$', 'n');
select email from person where regexp_like(email, '^james.*com$', 'm');
select email from person where regexp_like(email, '^li.*com$');
select email from person where regexp_like(email, '^li.*com$', 'm');
select email from person where regexp_like(email, '^li.*com$', 'n');
/*regexp_instr()===================================================================================
regexp_instr(x,pattern[,start[,occurrence[,return_option[,match_option]]]])
參數說明:
x 待匹配的字符串
pattern 正則表達式元字符構成的匹配模式
start 開始匹配位置,如果不指定默認為1
occurrence 匹配的次數,如果不指定,默認為1
return_option 指定返回的類型,若該參數為0,則返回值為匹配位置的第一個字符,若為非0,則返回匹配值的最后一個位置+1
match_option 意義同regexp_like的一樣
=================================================================================================*/
--查找zip中第一個非數字字符的位置
select a.*, regexp_instr(zip,'[^[:digit:]]') as position from person a ;
--查找zip中,從第2位開始第2次匹配的最后一個字符位置+1
select a.*, regexp_instr(zip,'[^[:digit:]]',2,2,1) as position from person a ;
--查找zip中,從第1位開始第2次匹配的最后一個字符位置+1
select a.*, regexp_instr(zip,'[^[:digit:]]',1,2,1) as position from person a ;
--查找zip中,從第1位開始第1次匹配的最后一個字符位置+1
select a.*, regexp_instr(zip,'[^[:digit:]]',1,1,1) as position from person a ;
--返回21,從第1個字符開始,找出以o開頭 以e結尾 中間跟4個任意字母的單詞 第1次匹配的第1個字符位置,這里是oracle中o的位置
select regexp_instr('i love http://www.52oracle.com','o[[:alpha:]]{4}e',1,1) as r from dual
--返回24,從第1個字符開始,找出以o開頭 后跟2個任意字母的單詞 第2次匹配的第1個字符位置,這里是ora中o的位置
select regexp_instr('i love http://www.52oracle.com','o[[:alpha:]]{2}',1,2,1) as r from dual
--返回17,從第1個字符開始,找出l開頭的 后跟4個任意字母的單詞 第1次匹配的第1個字符的位置,這里是light中l的位置
SELECT REGEXP_INSTR('But, soft! What light through yonder window breaks?','l[[:alpha:]]{4}',1,1,0) FROM DUAL;
--返回22,從第1個字符開始,找出l開頭的 后跟4個任意字母的單詞 第1次匹配的最后一個字符的位置+1,這里是light中t的位置+1
SELECT REGEXP_INSTR('But, soft! What light through yonder window breaks?','l[[:alpha:]]{4}',1,1,1) FROM DUAL;
/*regexp_substr()===================================================================================
regexp_substr(x,pattern[,start[,occurrence[match_option]]])
參數說明:
x 待匹配的字符串
pattern 正則表達式元字符構成的匹配模式
start 開始匹配位置,如果不指定默認為1
occurrence 匹配的次數,如果不指定,默認為1
match_option 意義同regexp_like的一樣
=================================================================================================*/
--查找第一個非0字符值
select a.* , regexp_substr(zip, '[^[:digit:]]') as zip from person a ;
--從第三個字符開始,查找第2個非0字符值
select a.* , regexp_substr(zip, '[^[:digit:]]', 3, 2) as zip from person a;
--查找以o開始的,后面接4個字母的字符串
select regexp_substr('I love oracle very much','o[[:alpha:]]{4}') from dual;
--查找以o開始的,后面至少接4個字母的字符串
select regexp_substr('I love oracle very much','o[[:alpha:]]{4,}') from dual;
--查找以o開始,以e結尾的,后面接1個或多個除null之外字符的字符串
select regexp_substr('i love oracle very much','o.{1}e',1,1) from dual;
select regexp_substr('i love oracle very much','o.*e',5,1) from dual;
/*regexp_replace()===================================================================================
regexp_replace(x,pattern[,replace_string[,start[,occurrence[match_option]]]])
參數說明:
x 待匹配的字符串
pattern 正則表達式元字符構成的匹配模式
replace_string 替換字符串
start 開始匹配位置,如果不指定默認為1
occurrence 匹配的次數,如果不指定,默認為1
match_option 意義同regexp_like的一樣
=================================================================================================*/
--把zip中所有非數字字符替換為0
update person set zip=regexp_replace(zip, '[^[:digit:]]', '0')where regexp_like(zip, '[^[:digit:]]');
select zip from person;
--后向引用:
--后向引用是 一個很有用的特性。它能夠把子表達式的匹配部分保存在臨時緩沖區中,供以后重用 。緩沖區從左至右進行編號,
--並利用 \digit 符號進行訪問。子表達式用一組圓括號來顯示。利用后向引用可以實現較復雜的替換功能。
select regexp_replace('Steven Chen', '(.*) (.*)', '\2, \1') as reversed_name from dual;
--修改person表,增加檢查zip的第一個字符是否為數字的檢查索引
alter table person add constraint constraint_zip check (regexp_like(zip, '^[[:digit:]]+$'));
--根據姓的第一個大寫字母創建索引
create index person_idx on person(regexp_substr(last_name, '^[[:upper:]]'));
select *
from person a
where regexp_substr(last_name, '^[[:upper:]]')='W'
-- 用‘XXX’代替‘light’ , 返回But, soft! What XXX through yonder window breaks?
SELECT REGEXP_REPLACE('But, soft! What light through yonder window breaks?','l[[:alpha:]]{4}','XXX') FROM DUAL;
--用’XXX‘代替以e開始,長度為3的字符串,從第5個字符開始,匹配2次
select regexp_replace('hello everybody,may I have your attention please?','e[[:alpha:]]{2}','XXX',5,2) from dual;
--大小寫敏感
select regexp_replace('hello Everybody,may I have your attention please?','e[[:alpha:]]{2}','XXX',5,1) from dual;
--忽略大小寫
select regexp_replace('hello Everybody,may I have your attention please?','e[[:alpha:]]{2}','XXX',5,2,'i') from dual;