摘要: l 方括號表達示方括號表達式描述[[:alnum:]]字母和數字混合的字符[[:alpha:]]字母字符[[:cntrl:]]控制字符[[:digit:]]數字字符[[:graph:]]圖像字符[[:lower:]]小寫字母字符[[:print:]]打印字符[[:punct:]]標點符號字符[[:spac... 閱讀全文
簡要比較: replace 字符串級別的代替 如:SELECT REPLACE('accd','cd','ef') from dual; --> aefd
translate 字符級別的代替 如:select translate('acdd','cd','ef') from dual; -->aeff replace('將要更改的字符串','被替換掉的字符串','替換字符串') 例:select replace ('111222333444','222','888') from dual; 輸出為 '111888333444' 分別詳解 replace: 語法:REPLACE(char,search_string[,replacement_string]) 解釋:replace中,每個search_string都被replacement_string所代替 select replace('acdd','cd','ef') from dual; --> aefd
如果replacement_string為空或為null,那么所有的search_string都被移除 select replace('acdd','cd','') from dual; --> ad
如果search_string 為null,那么就返回原來的char select replace('acdd','ef') from dual; -->acdd select replace('acdd','','') from dual; -->acdd(也是兩者都為空的情況)
translate: 語法:TRANSLATE('char','from_string','to_string') 解釋:translate中,每個from_string中的字符被to_string中
舉例說明: select translate('asd12fg','12','55') from dual
oracle的substr函數的用法 select substr('Thisisatest', -4, 2) value from dual 結果是 te select substr('emros',-3,1) value from dual 結果是 r
substr('abcde',-6) = null
INSTR
(源字符串, 目標字符串, 起始位置, 匹配序號) 在Oracle/PLSQL中,instr函數返回要截取的字符串在源字符串中的位置。只檢索一次,就是說從字符的開始 到字符的結尾就結束。 語法如下: instr( string1, string2 [, start_position [, nth_appearance ] ] ) 參數分析: string1 源字符串,要在此字符串中查找。 string2 要在string1中查找的字符串. start_position 代表string1 的哪個位置開始查找。此參數可選,如果省略默認為1. 字符串索引從1開始。如果此參數為正,從左到右開始檢索,如果此參數為負,從右到左檢索,返回要查找的字符串在源字符串中的開始索引。 nth_appearance 代表要查找第幾次出現的string2. 此參數可選,如果省略,默認為 1.如果為負數系統會報錯。 注意: 如果String2在String1中沒有找到,instr函數返回0. select instr('adsda','a') from dual select instr('adsda','a',1,2) from dual select instr('adsda','a',-1,2) from dual ORACLE中的支持正則表達式的函數主要有下面四個: 例子:判斷姓名是否為空,少于兩個字符,包含數字和字母 create or replace 需求: 匹配手機號,第一位可以是+,可以沒有+,后面的全部要是數字,如: +861359415665 8613659558555 1356856455 都是合法的。 +aa156945555aa1359556666 aaddssdfdfsd 都是不合法的。 正則: [sql]
[sql]
解釋: 1.^代表開始,*表示出現0次或多次,+表示出現1次或多次,[:digit:]代表0-9的純數字(還有$代表以什么結尾,如果是[[:digit:]]+$代表以數字結尾)。該正則的意思就是: 以+0次或多次開頭,緊接著后面數字出現一次或多次(即一定要有數字)。 2.dual表中,永遠只有1行記錄。查詢出dual中有記錄,證明where條件成立,反之不成立。 先前寫了一個錯誤的正則: [sql]
注意,就只少了一個代表開始符號的^。少了這個符號,說明這個正則的意思是: +出現0次或多次(即+可以出現,可以不出現!!),緊后面的數字出現1次或多次。前面已經+可以出現0次了,證明沒有+也可以,那么就是只要字符串中有數字(+aa111a,aass11111……),這個正則恒成立,錯誤深重啊!! Oracle正則表達式的應用by 溫州--名次 在oracle里正則表達式有四個函數可用,分別是regexp_like、regexp_substr、regexp_instr 和regexp_replace。這里在我們oracle 10g里靈活應用。 先來簡單介紹一下正則表達式的內容,正則表達式是做為快速查詢的文本內容的,在linux應用比較多,首先,行的起始與結束 “^”這個字符是表示只查找行首的內容。“$”這個字符只查找行末的內容。接下來是“^”還可以做為一個排除字符來使用。還是使用例子來做一個演示比較明了一下。 這里我使用regexp_like這個函數來做,這樣可以我們平時會使用的比較多。 select * from test_table where regexp_like(field_1,'^1234') 這個就是表示是以1234打頭的字符串是不是有匹配的。這里和like的方式是一樣的。
select * from test_table where regexp_like(field_1,'^[12]234') 這里多了一個[]這里做一個獨立字符,這里表示是以1或2開始,并且接著是234這個里的字符就會是匹配的。
select * from test_table where regexp_like(field_1,'^(歐陽|李)小二') 這里我們就可以表達,這個查詢一個姓是歐陽或李的,名字叫小二的字符串。這里多了一個()這個是做一個為字符串的方式來寫的與[]剛好是對應。 這里還有一個“|”來表示或的意思。
select * from test_table where regexp_like(field_1,'^李[小]*二') 這里我們就可以查詢李小二或是李二,再或者是李小小二,都可以,這里我們需要講一下是[]后面帶了一個*,這個是表示0~無窮大 字符去匹配。這個[]我們還可以添加一個“+”來表示1~無窮大的字符去匹配,也可以更加精準一些,在[]后面{1,3}這里就是表示1個到3個相同字符的匹配。還有一個“?”來說表示1或是0個。
select * from test_table where regexp_like(field_1,'李[^小]二') 這里我們可以查詢到姓李的,但是第二字不是“小”這個字。
select * from test_table where regexp_like(field_1,'[0-9]') 這里是表示我們查詢字符串含有0-9的數字的字符串。
select * from test_table where regexp_like(field_1,'[a-z]') 這里是表示我們查詢字符串含有a-z的小寫字母的字符串。
select * from test_table where regexp_like(field_1,'[A-z]') 這里是表示我們查詢字符串含有A-z的所有字母的字符串。
select * from test_table where regexp_like(name,'[[:alpha:]]') 這里是表示查詢匹配任意字母,也包括中文字
select * from test_table where regexp_like(name,'[[:alnum:]]') 這里是表示查詢匹配任意字母和數字
select * from test_table where regexp_like(name,'[[:digit:]]') 這里是表示查詢匹配任意數字
Select * from test_table Where regexp_like(name,’of’,’i’) 這里就是of不區分大小寫
Select * from test_table Where regexp_like(name,’^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$’) 這樣我們可以查詢是不是ip格式
接下來介紹一下regexp_substr 這個也是一個非常實用的一個函數
REGEXP_SUBSTR與SUBSTR函數相同,返回截取的子字符串 REGEXP_SUBSTR(srcstr, pattern [, position [, occurrence [, match_option]]]) 注: srcstr 源字符串 pattern 正則表達式樣式 position 開始匹配字符位置 occurrence 匹配出現次數 match_option 匹配選項(區分大小寫)
SELECT regexp_substr('1PSN/231_3253/ABc', '[[:alnum:]]+') FROM dual; Output: 1PSN [[:alnum:]]+ 表示匹配1個或者多個字母或數字字符
SELECT regexp_substr('1PSN/231_3253/ABc', '[[:alnum:]]+', 1, 2) FROM dual; Output: 231 與上面一個例子相比,多了兩個參數 1 表示從源字符串的第一個字符開始查找匹配 2 表示第2次匹配到的字符串(默認值是“1”,如上例)
select regexp_substr('@@/231_3253/ABc','@*[[:alnum:]]+') from dual; Output: 231 @* 表示匹配0個或者多個@ [[:alnum:]]+ 表示匹配1個或者多個字母或數字字符 注意:需要區別“+”和“*”的區別
select regexp_substr('1@/231_3253/ABc','@+[[:alnum:]]*') from dual; Output: @ @+ 表示匹配1個或者多個@ [[:alnum:]]* 表示匹配0個或者多個字母或數字字符
select regexp_substr('1@/231_3253/ABc','@+[[:alnum:]]+') from dual; Output: Null @+ 表示匹配1個或者多個@ [[:alnum:]]+ 表示匹配1個或者多個字母或數字字符
select regexp_substr('@1PSN/231_3253/ABc125','[[:digit:]]+$') from dual; Output: 125 [[:digit:]]+$ 表示匹配1個或者多個數字結尾的字符
select regexp_substr('1@/231_3253/ABc','@+[[:alnum:]]+') from dual; Output: Null @+ 表示匹配1個或者多個@ [[:alnum:]]+ 表示匹配1個或者多個字母或數字字符
select regexp_substr('@1PSN/231_3253/ABc125','[[:digit:]]+$') from dual; Output: 125 [[:digit:]]+$ 表示匹配1個或者多個數字結尾的字符
select regexp_substr('@1PSN/231_3253/ABc','[^[:digit:]]+$') from dual; Output: /ABc [^[:digit:]]+$ 表示匹配1個或者多個不是數字結尾的字符
select regexp_substr('Tom_Kyte@oracle.com','[^@]+') from dual; Output: Tom_Kyte [^@]+ 表示匹配1個或者多個不是“@”的字符
select regexp_substr('1PSN/231_3253/ABc','[[:alnum:]]*',1,2) from dual; Output: Null [[:alnum:]]* 表示匹配0個或者多個字母或者數字字符 注:因為是匹配0個或者多個,所以這里第2次匹配的是“/”(匹配了0次),而不是“231”,所以結果是“Null”
這里我們有時候會查詢字符串里asdfafd<main>dafda 這里我們要取出<main>這個字符串 Select regexp_substr('asdfafd<main>dafda','<[^>]+>') from dual Output: <main> 這里我們在<>中間去一個^>這樣在匹配<之后,在向后查詢的時候確保在匹配到>之前不再在有>,不然的話就要有可以出錯的情況。
Select regexp_substr('asdfafd<main>da>fda','<[^<]+>') from dual Output: <main>da> 在這個例子中,我們在<main>之后還在da>,這樣的話,如果我們沒有添加^>,正則表達式就會向后繼續去匹配,直到最后一個>為至,這樣就會出現偏差
這個通常用來實現字符串的列傳行 select regexp_substr('123;234;345;456;567;678;789','[^;]+',1,rownum) from dual connect by rownum <= length('123;234;345;456;567;678;789') - length(replace('123;234;345;456;567;678;789',';'))+1 這里length這里操作是先得到有多少個“;”,再通過 connect by rownum方式來做一行成多行的操作,在變成多行之后,可以通過regexp_substr來取字符串的操作
接著上一個例子 a,b,c,d,e,d,f,a,n這樣的一個字符串,我們現在要把字符串里一些重復去掉,這樣的話結果是a,b,c,d,e,f,n去掉了d與a的兩個字符串 select wm_concat(new_row) from ( select distinct regexp_substr('a,b,c,d,e,d,f,a,n','[^,]+',1,rownum) new_row from dual connect by rownum<=length('a,b,c,d,e,d,f,a,n')-length(replace('a,b,c,d,e,d,f,a,n',','))) 通過轉成多行的,再用distinct 去掉重復,然后我們再通過wm_concat來字符串合并來完成。
再來一個ip格式轉換的例子吧,我們一般的IP的格式是12.19.168.27現在要不足3位的補足前面為0,結果是012.019.168.027 select wm_concat(new_value) from ( select lpad(regexp_substr('12.19.168.27','[^.]+',1,rownum) ,3,'0') new_value,rownum from dual connect by rownum<5 order by rownum)
來一個驗證IP是數字是否正確 select count(*) from( select lpad(regexp_substr('12.19.168.27','[^.]+',1,rownum) ,3,'0') new_value,rownum from dual connect by rownum<5) where new_value>=0 and new_value<256 having count(*) =4
來一個IP字符串格式轉換成數字型IP select sum(new_value*power(256,4-rm)) from ( select regexp_substr('12.19.168.27','[^.]+',1,rownum) new_value,rownum rm from dual connect by rownum<=4 )
接下來介紹一個regexp_instr函數
REGEXP_INSTR 函數使用正則表達式返回搜索模式的起點和終點。REGEXP_INSTR 的語法如下所示。REGEXP_INSTR 返回一個整數,指出搜索模式的開始或結束的位置,如果沒有發現匹配的值,則返回0。
語法: 2.REGEXP_INSTR與INSTR函數相同,返回字符串位置 REGEXP_INSTR(srcstr, pattern [, position [, occurrence [, return_option [,match_option]]]]) 與REGEXP_SUBSTR一樣,它也有變量pattern、position(開始位置)、occurrence 和match_parameter;這里主要介紹一下新參數return_option 的作用,它允許用戶告訴Oracle,模式出現的時候,要返回什么內容。
Select regexp_instr('asdfafd<main>da>fda','sd') from dual Output:2 這里去查詢sd的位置,這個和instr是在相同的
Select regexp_instr('asdfafd<main>da>fda','da',1,2) from dual 這里是查詢da第二出現的位置
還有我們經常會遇到一種情況是,查詢某個字段,如果是等于“上海”或“北京”或者我們溫州就寫成大城市,其它的寫成小城市,我們一般會考慮使用decode這種方式
Select decode('上海','上海','大城市','北京' ,'大城市' ,'溫州' ,'大城市','小城市') from dual 只有兩個我們可能覺的sql也不是很冗長,如果有四五個的話,就有點長了,這里使用regexp_instr就可以很多的去操作
Select decode (regexp_instr('北京','^(上海|北京|溫州)'),0,'小城市', '大城市') from dual 通過regexp_instr不匹配時為0的條件,這樣就可以完成了
最后一個函數regexp_replace REGEXP_REPLACE 函數是用另外一個值來替代串中的某個值。例如,可以用一個匹配數字來替代字母的每一次出現。REGEXP_REPLACE的格式如下所示
語法: 4.REGEXP_REPLACE與REPLACE函數相同,替換原字符串中的字符內容 REGEXP_REPLACE(srcstr, pattern [,replacestr [, position [, occurrence [,match_option]]]])
這個替換函數還是一個非常好用的。 如我們在有一個字符串adfadfa (main) next 現在我們要把()替換成<>,這里我們可能想用replace就可以搞定了,但是我們現在做的是(之后必須有)這樣的()我們才替換把<>. select regexp_replace('adfadfa (main) next ','(\()([^\)]*)(\))','<\2>') from dual output: adfadfa <main> next 這里還是一個\做為轉義字符。
再來一個ip格式轉換的例子吧,我們一般的IP的格式是12.19.168.27現在要不足3位的補足前面為0,結果是012.019.168.027 select regexp_replace( regexp_replace('12.19.168.27','([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})', '00\1.00\2.00\3.00\4') , '([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}$)','\2\4\6\8') from dual output: 012.019.168.027 這里我分成兩步來操作,regexp_replace('12.19.168.27','([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})', '00\1.00\2.00\3.00\4')我首先讓每個小字符串做添加0,這樣每個字符串都會大于3,再 '([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}\.)([0-9]*)([0-9]{3}$)','\2\4\6\8') 這整個字符串分成8段,這樣我們只要2、4、6、8這四個段就可以了。
下面一個例子中,在每兩個字符之間插入一個空格符 SELECT regexp_replace('YAHOO', '(.)', '\1 ') AS output FROM dual; Output: Y A H O O 這個用一個循環的方式去操作,還蠻好的。
select regexp_replace( regexp_replace('12.19.168.27','([^.]+)' ,'00\1') ,'([^.]*)([^.]{3})','\2') from dual 接著剛才那個,我們可以把replace循環替換的方式來操作。 正則表達式,給我寫個1,2,3,4 或者4,1,2,3 匹配出4 來 select regexp_substr('1,2,3,4','[4]') tony from dual; select regexp_substr('4,3,2,1','[4]') tony from dual;
oracle 驗證電話號碼(手機號碼): /** * 手機號碼 * 移動:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 * 聯通:130,131,132,152,155,156,185,186 * 電信:133,1349,153,180,189 */ select t.* from myregex t where regexp_like(t.name,'^1(3[0-9]|5[0-35-9]|8[025-9])[0-9]{8}$') select t.* from myregex t where regexp_like(t.name,'^1(3[0-9]|5[0-35-9]|8[025-9])?[0-9]{8}?$') select t.* from myregex t where regexp_like(t.name,'^1(3[[:digit:]]|5[0-35-9]|8[025-9])?[[:digit:]]{8}?$') /** * 中國移動:China Mobile * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 */ select t.* from myregex t where regexp_like(t.name,'^1(34[0-8]?|3[5-9]?|5[017-9]?|8[278]?)[0-9]{8}$') select t.* from myregex t where regexp_like(t.name,'^1(34[0-8]?|3[5-9]?|5[017-9]?|8[278]?)[[:digit:]]{8}$') /** * 中國聯通:China Unicom * 130,131,132,152,155,156,185,186 */ select t.* from myregex t where regexp_like(t.name,'^1(3[0-2]?|5[25-6]?|8[5-6]?)[0-9]{8}$') select t.* from myregex t where regexp_like(t.name,'^1(3[0-2]?|5[25-6]?|8[5-6]?)[[:digit:]]{8}$') /** * 中國電信:China Telecom * 133,1349,153,180,189 */ select t.* from myregex t where regexp_like(t.name,'^1((33?|53?|8[09]?)[0-9]?|349)[0-9]{7}$') select t.* from myregex t where regexp_like(t.name,'^1((33?|53?|8[09]?)[0-9]?|349)[[:digit:]]{7}$') NULL指的是空值,或者非法值。 select t.empno,nvl(t.mgr,'MGR') from emp t where t.deptno in (select s.deptno from dept s where s.deptno='1')
select t.empno,nvl(t.mgr,'MGR') from emp t where exists (select s.deptno from emp s where s.deptno='1' and t.deptno=s.deptno) select t.empno,nvl(t.mgr,'MGR') from emp t where t.deptno is not null and exists (select s.deptno from emp s where s.deptno='1' and t.deptno=s.deptno) select t.empno,nvl(t.mgr,'MGR') from emp t where not exists (select s.* from dept s where s.deptno in(2,3) and t.deptno=s.deptno) select t.empno,nvl(t.mgr,'MGR') from emp t where t.deptno in (select s.deptno from dept s where s.deptno not in(2,3)) package com.abin.lee.servlet.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static boolean isRight(String validate){ String regex="/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/";//郵箱正則1 // String regex="(^[\\w]*@[a-zA-Z]+[.][a-zA-Z]+$)";//郵箱正則1 // String regex="(^13[0-9]{9}$)|(^15[0-9]{9}$)|(^18[0-9]{9}$)";//電話號碼正則 Pattern pattern=Pattern.compile(regex); Matcher matcher=pattern.matcher(validate); boolean flag=matcher.matches(); return flag; } public static void main(String[] args) { String validate="varyall@tom.com"; boolean flag=isRight(validate); System.out.println("flag="+flag); } }
|