mysql - varchar類型與數字的比較和轉換


mysql - varchar類型與數字的比較和轉換

convert(對象, 目標類型)是mysql中常用的類型轉換對象函數。eg: select convert(‘1.123’, decimal(10.4)),結果就是1.1230。對象可以用列名替代。

前兩天發現,一個小伙伴之前設計表時把某個表數據類型設計成了varchar,實際用於存儲Decimal。我需要用其數據進行過濾篩選,這就造成了一些不便,所以記錄了本文。

如果文章內容有問題,歡迎評論或與我進行討論(請注明原因):

mail: wgh0807@qq.com
微信: hello-wgh0807
qq: 490536401

結論

使用convert或直接進行數字比較,在字符串與數字進行比較時,先對字符串進行了解析,遇到非數字類型(即字母等)會停止識別,然后將成功解析的部分(從左到右,異常為止)識別轉換為數字。如'1.56a8d7' -> 1.56'abcdefg...'->0

若確定數據實際上是數字類型,可以使用數字進行比較,如column>1.1

如果用到將數字存儲為字符串,需要轉換回數字或需要進行比較的操作,推薦使用convert方法。CONVERT(column, decimal(10,5)),數據類型可以按照實際需要修改。

發現問題

我一直習慣於在idea中Database console 下直接編寫sql語句完成所有對數據庫的操作,這次也是,我使用了以下sql進行查詢:select * from test_table where volume > 0 。由於數據量較大,並沒有發現什么問題,過濾掉了0.0000,效率還不錯。

測試結果1

可是組長大大喜歡用navicat,畢竟可視化,查詢、修改也方便。於是我也下載了一個,直觀的修改條件,查看結果。但卻篩選到出了錯誤的結果(如下圖):

從圖中我們可以看到,在navicat的shaix中以volume>0,’0.00’竟然成功通過篩選!我當時就懷疑sql設計的問題

分析測試

這里需要注意,我直接構建sql篩選用到的是整型的0,在sql語句中為 volume> 0,但是使用navicat時,由於表項類型是varchar,故其經過識別,在組裝成sql的時候變成volumn > '0',在比較過程中采用的是字符串的比較,故'0.0'>'0'

目測沒啥問題了,但是心虛的我又編寫了一個測試sql,用於計數:

select count(*) from (SELECT * FROM lh_dc_bond_price_net WHERE dq_volume > 0) a where dq_volume like '0.00%';

計數結果為空,我放心了。突然小伙伴-霖提問:如果出現字母會怎么樣呢?可以正確識別嗎?識別正確的部分?還是會報錯?

我做了個實驗:

select '1.23a>1.23','1.23a'>1.23 UNION select '1.23a<1.23','1.23a'<1.23 UNION select '1.23a=1.23','1.23a'=1.23;

SELECT '1a.23>1','1a.23'> 1 UNION SELECT '1a.23<1','1a.23'< 1 UNION SELECT '1a.23=1','1a.23'=1;

SELECT 'a>0','a'>0 UNION SELECT 'a<0','a'<0 UNION SELECT 'a=0','a'=0;

三次結果都是0,0,1由此可得,在字符串與數字進行比較時,先對字符串進行了解析,將成功解析的部分(從左到右,異常為止)識別轉換為數字。 此處和convert轉換結果相同。

小結:若需要進行比較,則可以直接讓字符串與數字進行比較。若需要獲得對象轉換后的值,則需要使用convert函數或cast進行轉換。

mysql 5.7 數據類型轉換方法總結

此部分主要參考mysql參考文檔 - 12.10 Cast Functions and Operators

常用的轉換方法:BINARY、CAST、CONVERT。

  • BINARY expr將對象轉換為二進制格式,常用語區分大小寫和檢測空格。

  • CAST(expr AS type):接收任意類型的表達式並生成指定類型的結果值,功能和語法類似於CONVERT。是標准SQL語法。

  • Convert(expr,type)Convert(expr using transcoding_name)。可以采用任何類型表達式生成指定類型的結果值。

    • Convert(expr,type)等價於CAST(expr AS type)函數。
    • Convert(expr using transcoding_name) 是標准SQL語法。在不同編碼格式下轉換

convert未使用using 和 cast 時,type的類型可以包括以下值

  • BINARY[(N)]

    生成具有BINARY數據類型的字符串 。有關如何影響比較的說明,請參見 第11.4.2節“BINARY和VARBINARY類型”。如果N給出了可選長度 ,則 會使強制轉換使用不超過 參數的字節。短於字節的值用字節填充到長度為 。 BINARY(N)NN0x00N

  • CHAR[(N)] [charset_info]

    生成具有CHAR數據類型的字符串 。如果N給出了可選長度,則會使強制轉換使用不超過 參數的字符。對於短於字符的值,不會出現填充 。

    如果沒有charset_info子句,則 CHAR生成具有默認字符集的字符串。要明確指定字符集,charset_info允許使用以下值:

    • CHARACTER SET charset_name:生成具有給定字符集的字符串。

    • ASCII:簡寫 CHARACTER SET latin1。

    • UNICODE:簡寫 CHARACTER SET ucs2。

    在所有情況下,字符串都具有字符集的默認排序規則。

  • DATE

    產生DATE值。

  • DATETIME

    產生DATETIME值。

  • DECIMAL[(M[,D])]

    產生DECIMAL值。如果給出了可選值M和 D值,則它們指定最大位數(精度)和小數點后面的位數(刻度)。

  • JSON (在MySQL 5.7.8中添加)

    產生JSON值。有關在JSON其他類型之間轉換值的規則的詳細信息 ,請參閱 JSON值的比較和排序。

  • NCHAR[(N)]

    類似CHAR,但會產生一個帶有國家字符集的字符串。請參見 第10.3.7節“國家字符集”

    與CHAR不同,NCHAR不允許指定尾隨字符集信息。

  • SIGNED [INTEGER]

    生成有符號整數值。

  • TIME

    產生TIME價值。

  • UNSIGNED [INTEGER]

    生成無符號整數值。

更多信息請見 mysql 參考手冊

參考文檔:

MySQL中字符串與數字比較的坑 - Live In A Dream

mysql參考文檔 - 12.3.2 Comparison Functions and Operators

[mysql參考文檔 - 12.10 Cast Functions and Operators](


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM