天天看點

mysql判斷純數字_MYSQL中判斷字元串是否為純數字

今天下午産品的需求中要求要把一個資料庫字段類型是text類型,但是字段裡面的字段值是純數字的記錄找出來做統計使用,開始覺得不能夠實作,後面網上查了一下,最後按照産品的要求做出來了,但是實作的過程中出現一些小坑,并且發現網上的說法中有的是錯誤的,做一個糾正。

最開始的時候通過網上查資料搜到的方法是想通過正則比對。(之前有個錯誤的認識,覺得正則比對會嚴重影響效率)。不是特别願意使用正則比對,想通過其他方式實作。正好看到一個人提了一種方法。

"select * from tt where length(0+name)=length(name);"

我按照這個方法寫了一下,跑了一下貌似可以,但是這個字段中會有存放'-'和'+'的情況,這種情況下的也被篩選了出來。然後再加個篩選條件把這兩種情況過濾出去。這樣表面上看是可以了。

但是得需要把這個寫法的原了解釋清楚,就接着找了一下mysql中length()的作用,網上查出來的作用是:mysql的一個用來來擷取字元串長度的内置函數方法。按照這個作用的思路來的話,是解釋不通的。但是為什麼能查出來結果呢!?

然後就把關鍵部分單獨拿出來,在mysql中執行

sql語句

運作結果

select LENGTH('test') as test1;

4

select LENGTH(0+'test') as test2;

1

select 0+'test' as test3;

select LENGTH('30') as test4;

2

select LENGTH('30'+0) as test5;

2

select '30'+0 as test6;

30

從上面的結果中,這就能說明問題了:字段類型是char,字段值是字元串的話,把字段的值加上0得到的結果是0。但字段值是要是數字的話,它加0的時候是把它當成數字在加的。那麼這種情況下,數字在加0前後的長度是不變化的,确實能篩選出來;字元串的話在加了0之後長度就變成1了,就不等了就被過濾了出去(這裡面有一個十分嚴重的坑,就是我測試的時候,資料庫裡面的字元串沒有長度為1的字元串。加0操作後長度就變化了。)其實'-'和'+'也被篩選出來,就是因為它們的長度是1.但是這兩個符号特殊,讓我産生了誤解,朝着把它們了解成是正号和負号的方向去考慮了。這點上也說明了想測試用例的時候,覆寫面要廣是多麼的重要!!!

接下來就确定下來使用正則規則去比對。剛開始寫出來的sql:

SELECT * FROM TEST WHERE (RESULT REGEXP '[^0-9.]') = 0;

{String} REGEXP '[^0-9.]'的作用就是如果String中含有不是0-9之間的數字或者是小數點時,傳回true(1) ,反之則傳回false(0)。傳回值是0的時候正好符合我們的要求。

對正則熟悉的人就能馬上看出問題來。

這樣的話,是能把含有數字的字段過濾出來,但是出現類似'1.2.2.2.2'這種規則的數字的話也能被篩選出來,但是這在數學上是錯誤的,不能用來進行計算的。是以需要進一步修改,又得到如下寫法:

SELECT * FROM TEST WHERE RESULT REGEXP '(^[0-9].[0-9]$)|(^[0-9]$)'

這種寫法是隻能限定死得到的小數類型在整數部分隻能有一位。再經過查詢資料最後得到寫法

SELECT * FROM TEST WHERE RESULT REGEXP '(^[0-9]+.[0-9]+$)|(^[0-9]$)'

過程中查詢到有價值的資訊:

過程中,思路來源于參考了以下博文:

最後看一下剛開始擔心的效率問題:

一共9125條資料,

SELECT * FROM TEST 用時:0.015

SELECT * FROM TEST WHERE RESULT REGEXP '(^[0-9]+.[0-9]+$)|(^[0-9]$)' 用時:0.028

SELECT * FROM TEST WHERE RESULT REGEXP '(^[0-9].[0-9]$)|(^[0-9]$)' 用時:0.018

可以看出要是規則複雜的正規表達式的話,效率上确實是會有明顯的影響的。