oracleRegex

來源:互聯網
上載者:User

需求:

匹配手機號,第一位可以是+,可以沒有+,後面的全部要是數字,如:

+861359415665

8613659558555

1356856455

都是合法的。

 

+aa156945555

aa1359556666

aaddssdfdfsd

都是不合法的。

正則:

SQL> SELECT * FROM DUAL WHERE regexp_like('+333333' ,'^[\+]*[[:digit:]]+');      --該+轉義或者不轉義,結果是一樣的DUMMY-----X

 

SQL> SELECT * FROM DUAL WHERE regexp_like('aa333333' ,'^[+]*[[:digit:]]+');DUMMY-----

 

解釋:

1.^代表開始,*表示出現0次或多次,+表示出現1次或多次,[:digit:]代表0-9的純數字(還有$代表以什麼結尾,如果是[[:digit:]]+$代表以數字結尾)。該正則的意思就是:

以+0次或多次開頭,緊接著後面數字出現一次或多次(即一定要有數字)。

2.dual表中,永遠只有1行記錄。查詢出dual中有記錄,證明where條件成立,反之不成立。

先前寫了一個錯誤的正則:

[\+]*[[:digit:]]+

注意,就只少了一個代表開始符號的^。少了這個符號,說明這個正則的意思是:

+出現0次或多次(即+可以出現,可以不出現!!),緊後面的數字出現1次或多次。前面已經+可以出現0次了,證明沒有+也可以,那麼就是只要字串中有數字(+aa111a,aass11111……),這個正則恒成立,錯誤深重啊!!

OracleRegex的應用by 溫州--名次

在oracle裡Regex有四個函數可用,分別是regexp_like、regexp_substr、regexp_instr 和regexp_replace。這裡在我們oracle 10g裡靈活應用。

       先來簡單介紹一下Regex的內容,Regex是做為快速查詢的常值內容的,在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 Regex樣式

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>,這樣的話,如果我們沒有添加^>,Regex就會向後繼續去匹配,直到最後一個>為至,這樣就會出現偏差

 

 

這個通常用來實現字串的列傳行

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 函數使用Regex返回搜尋模式的起點和終點。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迴圈替換的方式來操作。

 

2010-7-5

轉載自:溫州--名次

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.