詳解MySQL中varchar和int隱式轉(zhuǎn)換的注意事項(xiàng)
一、前言
在一個(gè)陽光明媚的下午,我們的測(cè)試在運(yùn)行SQL是發(fā)現(xiàn)了一個(gè)靈異事件。
別著急,等我慢慢說來,是一個(gè)查詢庫(kù)存的SQL,控制臺(tái)打印了,查詢?yōu)?條記錄。
想著不太信,自己把SQL粘出來執(zhí)行一下,剛好有個(gè)varchar類型的字段,查詢的是一堆數(shù)字,忘記加引號(hào)了。
結(jié)果查詢出來了一條!
兩臉懵逼!
從頭看到結(jié)尾,發(fā)現(xiàn)我們查詢條件的字段值為231120103,把數(shù)據(jù)庫(kù)中231120103-1的查詢出來了!
經(jīng)過半天的探索,發(fā)現(xiàn)這是MySQL優(yōu)化器中,判斷數(shù)據(jù)類型不匹配的比較時(shí),MySQL 優(yōu)化器會(huì)進(jìn)行隱式類型轉(zhuǎn)換!
下面我們一起來看看這個(gè)隱式轉(zhuǎn)換,到底是怎么轉(zhuǎn)換的!
要知其然,知其所以然。
二、實(shí)踐出真知
1. 建表
CREATE TABLE `str_test` ( `id` int(0) NOT NULL, `str_column` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `int_column` int(0) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
我們新建一個(gè)表,里面有varchar和int類型,插入幾條方便測(cè)試!
INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (1, '123', 123); INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (2, '123-1---1122', 12); INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (3, 'abc', 1); INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (4, '783221667772672728', 2147483647); INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (5, '783221667772672798', 2147483647); INSERT INTO `test`.`str_test`(`id`, `str_column`, `int_column`) VALUES (6, '0', 0);
2. 測(cè)試查詢
我們先以int類型查詢varchar作為測(cè)試:
SELECT * FROM `str_test` WHERE str_column = 123;
大家是不是認(rèn)為這里只能查詢出一條數(shù)據(jù),答案是錯(cuò)誤的!我們后面統(tǒng)一說結(jié)論,這里先看測(cè)試!
我們?cè)诓迦胍粭lstr_column位數(shù)超過18位的!讓轉(zhuǎn)化是丟失精度,從而實(shí)現(xiàn)多查的情況!
我們看到查詢的和被查詢出來的是不一樣的!
我們?cè)谝詖archar來查詢int字段:
SELECT * FROM `str_test` WHERE int_column = '12A333';
還是可以查詢到數(shù)據(jù)!
3. 結(jié)論
經(jīng)過上面的測(cè)試是不是已經(jīng)汗流浹背了!不要慌,下面我們來揭曉答案!
有興趣的可以看看官網(wǎng)文檔:MySQL5.7文檔
當(dāng)整數(shù)與字符串進(jìn)行比較時(shí),無論數(shù)據(jù)庫(kù)是int還是varchar,只要類型不一致時(shí),MySQL會(huì)嘗試將字符串轉(zhuǎn)換為整數(shù)進(jìn)行比較。
如果字符串以有效的數(shù)字開頭,則將其轉(zhuǎn)換為相應(yīng)的整數(shù)值。
解析規(guī)則:從開頭解析直到遇到非數(shù)字的字符結(jié)束,前面的會(huì)作為比較的值,非數(shù)字后面的直接拋棄。
如果字符串以非數(shù)字字符開頭,將被轉(zhuǎn)化為0。
數(shù)值過大時(shí),回傳精度損失,也會(huì)出現(xiàn)匹配。沒找到具體的臨界值,超過18位會(huì)出現(xiàn)浮點(diǎn)數(shù)精度損失!
三、隱式轉(zhuǎn)換的缺點(diǎn)
精度損失: 隱式轉(zhuǎn)換可能導(dǎo)致精度損失問題,上面我們演示過了。
性能開銷: 在進(jìn)行大規(guī)模數(shù)據(jù)處理時(shí),頻繁的隱式轉(zhuǎn)換可能會(huì)對(duì)性能產(chǎn)生影響。
索引失效:存在隱式轉(zhuǎn)換會(huì)讓優(yōu)化器無法使用索引進(jìn)行優(yōu)化查詢,影響響應(yīng)時(shí)間。
數(shù)據(jù)安全風(fēng)險(xiǎn):如果是一個(gè)刪除語句,像上面演示的會(huì)出現(xiàn)匹配到其他行,從而導(dǎo)致數(shù)據(jù)被誤刪。還有多查的問題。
到此這篇關(guān)于詳解MySQL中varchar和int隱式轉(zhuǎn)換的注意事項(xiàng)的文章就介紹到這了,更多相關(guān)MySQL隱式轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一個(gè)單引號(hào)引發(fā)的MYSQL性能問題分析
剛剛我們說過了,生活中難免會(huì)有一些不如意,比如,我們用一個(gè)字符串類型的字段來作為主鍵,表面上,這太不如意了,然而,事實(shí)也證明這是有用的。2011-03-03mysql跨服務(wù)查詢之FEDERATED存儲(chǔ)引擎的實(shí)現(xiàn)
本文主要介紹了mysql跨服務(wù)查詢之FEDERATED存儲(chǔ)引擎的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01MySQL數(shù)據(jù)庫(kù)三種常用存儲(chǔ)引擎特性對(duì)比
MySQL中的數(shù)據(jù)用各種不同的技術(shù)存儲(chǔ)在文件(或內(nèi)存)中,這些技術(shù)中的每一種技術(shù)都使用不同的存儲(chǔ)機(jī)制,索引技巧,鎖定水平并且最終提供廣泛的不同功能和能力。在MySQL中將這些不同的技術(shù)及配套的相關(guān)功能稱為存儲(chǔ)引擎。2016-01-01MySQL的的數(shù)據(jù)一致性保障與延遲問題處理
在分布式數(shù)據(jù)庫(kù)和高并發(fā)應(yīng)用場(chǎng)景下,數(shù)據(jù)一致性 和 數(shù)據(jù)延遲 是兩個(gè)不可忽視的問題,MySQL 作為廣泛使用的關(guān)系型數(shù)據(jù)庫(kù),提供了多種機(jī)制來保障數(shù)據(jù)一致性,本文將深入探討 MySQL 如何保障數(shù)據(jù)一致性 以及 應(yīng)對(duì)數(shù)據(jù)延遲的策略,需要的朋友可以參考下2025-03-03MySQL中count()和count(1)有何區(qū)別以及哪個(gè)性能最好詳解
count是一個(gè)函數(shù),用來統(tǒng)計(jì)數(shù)據(jù),但是count函數(shù)傳入的參數(shù)有很多種,比如count(1)、count(*)、count(字段)等,下面這篇文章主要給大家介紹了關(guān)于MySQL中count()和count(1)有何區(qū)別以及哪個(gè)性能最好的相關(guān)資料,需要的朋友可以參考下2022-08-08