關(guān)于MySQL隱式轉(zhuǎn)換以及聚集函數(shù)問題

原本是因?yàn)橐粋€(gè)小小的問題,所以想對(duì)數(shù)據(jù)庫里的東西做個(gè)統(tǒng)計(jì),看看有沒有什么奇奇怪怪的數(shù)據(jù),然后就是漏打了個(gè)單引號(hào),發(fā)現(xiàn)了一個(gè)奇怪的現(xiàn)象。執(zhí)行的SQL如下:

select vc_full_name from t_fund_company_info WHERE vc_full_name=0;


結(jié)果發(fā)現(xiàn),哎,這怎么能查出數(shù)據(jù)庫里所有的數(shù)據(jù)呢,而且這里邊一個(gè)符合條件的結(jié)果都沒有,是不是MySQL抽了。

所以去問了一下別人,原來是MySQL的隱式轉(zhuǎn)換。

什么叫隱式轉(zhuǎn)換?

就是說,當(dāng)我們對(duì)不同類型的值進(jìn)行比較的時(shí)候,為了使得這些數(shù)值「可比較」(也可以稱為類型的兼容性),MySQL會(huì)做一些隱式轉(zhuǎn)化(Implicit type conversion)。

所以,上面那個(gè)語句,MySql在比較varchar類型和0的時(shí)候,會(huì)把varchar類型轉(zhuǎn)換成數(shù)字0

當(dāng)然MySQL也提供了這個(gè)cast()函數(shù),可以使用它來轉(zhuǎn)換成相應(yīng)的類型,就比如下面這個(gè)SQL:

select vc_full_name, ?cast(vc_full_name as SIGNED INTEGER) from t_fund_company_info;

結(jié)果如下:


那么,隱式轉(zhuǎn)換有什么規(guī)則呢,規(guī)則如下:

1.如果一個(gè)或兩個(gè)參數(shù)都是空的,比較的結(jié)果為null。null與null比較,結(jié)果為null,無需進(jìn)行轉(zhuǎn)換。

2.如果兩個(gè)比較的兩個(gè)參數(shù)都是string,按string比較,不做類型轉(zhuǎn)換。

3.如果兩個(gè)比較的兩個(gè)參數(shù)都是integer,按integer比較,不做類型轉(zhuǎn)換。

4.十六進(jìn)制的值和非數(shù)字做比較時(shí),會(huì)被當(dāng)做二進(jìn)制串來比較。

5.有一個(gè)參數(shù)是?TIMESTAMP?或?DATETIME,并且另外一個(gè)參數(shù)是常量,常量會(huì)被轉(zhuǎn)換為?timestamp。

6.有一個(gè)參數(shù)是?decimal?類型,如果另外一個(gè)參數(shù)是?decimal?或者整數(shù),會(huì)將整數(shù)轉(zhuǎn)換為?decimal?后進(jìn)行比較,如果另外一個(gè)參數(shù)是浮點(diǎn)數(shù),則會(huì)把?decimal?轉(zhuǎn)換為浮點(diǎn)數(shù)進(jìn)行比較

7.所有其他情況下,兩個(gè)參數(shù)都會(huì)被轉(zhuǎn)換為浮點(diǎn)數(shù)再進(jìn)行比較。

然后網(wǎng)上大家給出了一個(gè)需要注意的問題,就是:

假如password類型為字符串,查詢條件為 int 0 則會(huì)匹配上。

然后我就去數(shù)據(jù)庫操作了一下,發(fā)現(xiàn)有驚喜。


也就是說,這里是可以做SQL注入的。。如果網(wǎng)站登錄模塊做的比較挫的話。

所以說,為了防止在進(jìn)行查詢、更新或者刪除操作的時(shí)候,多操作更多的數(shù)據(jù),千萬記得寫SQL的時(shí)候加引號(hào)!

PS:最后沖哥還給出了一個(gè)重要結(jié)論, MySQL 隱式類型轉(zhuǎn)換本身也是非常耗費(fèi)?MySQL 服務(wù)器性能的,所以非常不推薦這樣使用。

第二個(gè)事情,是聚集函數(shù)的問題。這個(gè)聚集函數(shù),平時(shí)查數(shù)據(jù)庫也會(huì)用很多。

本來只想查下庫里一個(gè)文本字段,最大長(zhǎng)度是多少。結(jié)果發(fā)現(xiàn),這個(gè)里面的內(nèi)容跟對(duì)應(yīng)的長(zhǎng)度不符合。按照往常的習(xí)慣,沒多想,都是這樣寫的:

SELECT vc_fund_id,vc_fund_name,vc_Investment_field_txt,max(CHARACTER_LENGTH(vc_Investment_field_txt)) FROM t_fund_info;


但是TXT字段明顯沒有1305個(gè)字符。

后來才意識(shí)到,沒有加group by。。

在《數(shù)據(jù)庫系統(tǒng)概念》這本書中用如下的表述:

當(dāng)SQL查詢使用分組時(shí),一個(gè)很重要的事情是需要保證出現(xiàn)在select語句中但是沒有被聚集的屬性只能是出現(xiàn)在group by子句中的那些屬性,換句話說,任何沒有出現(xiàn)在group by子句中的屬性如果出現(xiàn)在select子句中的話,那么該屬性只能出現(xiàn)在聚集函數(shù)的內(nèi)部,否則,這樣的查詢就是錯(cuò)誤的。

所以說,比如有這樣一個(gè)表info,有如下字段:

id ?name ?num price

那么你這樣查:

select * from info group by id;

select id,sum(price) from info where price >= 10;

select id,count(price) from info where price >= 10;

select id, count(*) as num_prods, price from ?info where price >= 10;

這些都是錯(cuò)的!

第一個(gè)語句當(dāng)中,這個(gè)查詢按照id分組,然而select子句中的代表info中的所有屬性,更進(jìn)一步的,除了id之外,該表的其他屬性都未出現(xiàn)在group by子句中。所以是錯(cuò)的。

余下兩個(gè)也是一樣的。

最關(guān)鍵是,即使你這樣寫,MySQL也不會(huì)報(bào)錯(cuò)。。。但是結(jié)果卻讓你很困惑。。

大概所有數(shù)據(jù)庫都存在這種問題吧,像oracle、SQLserver等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是數(shù)據(jù)庫? 數(shù)據(jù)庫是存儲(chǔ)數(shù)據(jù)的集合的單獨(dú)的應(yīng)用程序。每個(gè)數(shù)據(jù)庫具有一個(gè)或多個(gè)不同的API,用于創(chuàng)建,訪問,管理...
    chen_000閱讀 4,144評(píng)論 0 19
  • 一、SQL速成 結(jié)構(gòu)查詢語言(SQL)是用于查詢關(guān)系數(shù)據(jù)庫的標(biāo)準(zhǔn)語言,它包括若干關(guān)鍵字和一致的語法,便于數(shù)據(jù)庫元件...
    shadow雨軒閱讀 587評(píng)論 0 3
  • 第四天 今天,你和我說你爸交給你的任務(wù),叫你去買月餅送給主任,突然意識(shí)到,現(xiàn)實(shí)就是這么殘酷,送禮無處不在。一個(gè)工作...
    筆尖的舞鞋閱讀 210評(píng)論 0 1
  • “看聶隱娘看到睡著的都是不懂藝術(shù),只知道爆米花的庸俗觀眾”??? 我就是那個(gè)看聶隱娘看睡著的low咖。但也別說我就...
    某琳閱讀 1,243評(píng)論 4 10
  • 儒雅風(fēng)范 幽默風(fēng)趣 生動(dòng)活潑 上的是感染與防御 鉤端螺旋體這一塊 你看她細(xì)長(zhǎng)柔軟的身軀 婀娜性感的腰肢 活潑可愛...
    李帥蛋閱讀 132評(píng)論 0 0

友情鏈接更多精彩內(nèi)容