- 資訊首頁(yè) > 網(wǎng)絡(luò )安全 >
- MySQL 中出現floor()報錯的原因是什么
這期內容當中小編將會(huì )給大家帶來(lái)有關(guān) 中出現floor()報錯的原因是什么,文章內容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
select count(*) from users group by concat(database(),floor(rand(0)*2)); select count(*),concat(database(),floor(rand(0)*2))x from users group by x;
它們表達的意思是一樣的,第二條語(yǔ)句中的as x其實(shí)就是concat(database(),floor(rand(0)*2))的代指(別名),這兩個(gè)SQL語(yǔ)句表達的意思并沒(méi)什么區別。來(lái),讓我們瞅瞅它報了什么錯:ERROR 1062 (23000): Duplicate entry 'security1' for key 'group_key'
它說(shuō)'group_key'的主鍵'security1'重復了,嗯?‘security1’從哪里來(lái)的?哪個(gè)表的主鍵重復了?
雖然剛開(kāi)始,咱們還不知道原理,但是可以看到報錯提示語(yǔ)句中的數據庫函數已經(jīng)被執行了。就像我之前說(shuō)的那樣,我本身有用到sqli-labs的數據庫,所以database()執行后是’security’很正常吧。
security1中的1便是來(lái)自floor(rand(0)*2),它說(shuō)security1重復,那說(shuō)明之前的表中已經(jīng)有這個(gè)主鍵了。因為database()固定,我們繼續來(lái)看下產(chǎn)生1的這個(gè)floor(rand(0)*2)。rand()同樣是一個(gè)數學(xué)函數,它返回一個(gè)隨機浮點(diǎn)值[0,1]。
若指定一個(gè)整數參數N,則它被作用種子值(也被叫為隨機因子),(rand()會(huì )根據這個(gè)種子值隨機生成)用來(lái)產(chǎn)生重復序列,也就是rand(0)的值重復計算是固定的。
而它后面的*2,則是選定獲取數據的范圍[0,2],其實(shí)就是乘以2。
floor()同樣是一個(gè)數學(xué)函數,返回不大于x的最大整數值,比如floor(3.3)返回3,floor(-3.3)返回-4。
現在讓我們看下計算users表數據的次數,floor(rand(0)*2)的值。
可以看到rand(0)的值確實(shí)是固定的。同時(shí)1也出現了。 concat()是字符串拼接函數,拼接多個(gè)字符串,如果字符串中含有NULL,則返回結果為NULL。這樣來(lái)看,concat后的結果為’security0’或’security1’,’security1’出現了。
分析到這,我們后半部分沒(méi)什么好說(shuō)的了,rand()還有一個(gè)非常重要的特性我們之后跟group by一起說(shuō)。
咱們再來(lái)說(shuō)這個(gè)count(*),這是一個(gè)聚合函數,返回值的數目,它與count()的區別是它不排除NULL。
咱們通過(guò)select count(*) from users group by username;這個(gè)查詢(xún)語(yǔ)句來(lái)了解下group by的工作過(guò)程。
group by在執行時(shí),會(huì )依次取出查詢(xún)表中的記錄并創(chuàng )建一個(gè)臨時(shí)表,group by的對象便是該臨時(shí)表的主鍵。如果臨時(shí)表中已經(jīng)存在該主鍵,則將count(*)值加1,如果不存在,則將該主鍵插入到臨時(shí)表中,注意是插入!查詢(xún)前創(chuàng )建的空臨時(shí)表。
取第一條記錄,username是Dumb,發(fā)現臨時(shí)表中沒(méi)有該主鍵,則將Dumb插入到主鍵,count(*)值計1,取第二條記錄。
同樣,取第二條記錄,username為Angelina,同樣沒(méi)有該主鍵,則將Angelina插入到主鍵,count(*)值計1。
當取到原表中第8條admin時(shí),同樣將admin作為主鍵插入到臨時(shí)表中,并將count(*)計1.當取第15條數據時(shí),發(fā)現臨時(shí)表中已經(jīng)有admin作為主鍵了,則直接count(*)加1。最終結果:
雖然在命令行中的顯示結果跟咱的不太一樣,但是思路是正確的(它貌似對結果按照字母進(jìn)行了排序,又或者在插入臨時(shí)表前就先進(jìn)行了排序)。
寫(xiě)到這里,那按照上面的邏輯,報錯語(yǔ)句應該是select count(*) from users group by ‘security0’或’security1’;啊?然后group by時(shí)創(chuàng )建臨時(shí)表,第一個(gè)是security0,發(fā)現沒(méi)有這個(gè)主鍵,此時(shí)將security0插入主鍵的位置,計1,然后取from的表中下一條記錄。
取下一條記錄,group by 后是‘security1‘,臨時(shí)表中不存在security1的主鍵,則將security1插入主鍵位置,計1,然后取下一條記錄。
之后group by 只有security0或security1,那應該只是計數上的變化了啊。最終應該是:
那為什么不是這個(gè)結果,反而報了主鍵重復的錯誤了呢?
因為還有一個(gè)最重要的特性,就是group by與rand()使用時(shí),如果臨時(shí)表中沒(méi)有該主鍵,則在插入前rand()會(huì )再計算一次(也就是兩次,但有些博客寫(xiě)的是多次,這個(gè)多次到底是幾次我并不知道,也沒(méi)有找到相關(guān)材料作為支持,但是以?xún)纱蝸?lái)理解下面的實(shí)驗都能說(shuō)的通),就是這個(gè)特性導致了主鍵重復并報錯。我們來(lái)看:
當group by 取第一條from 的表記錄時(shí),此時(shí)group by的是’security0’,發(fā)現臨時(shí)表中并沒(méi)有’security0‘的主鍵,注意,這個(gè)時(shí)候rand(0)*2會(huì )再計算一次,經(jīng)floor()后,率先插入臨時(shí)表的主鍵不是security0,而是security1,并計數1。
然后取第二條記錄,第二條記錄group by 的key中的01仍由floor(rand(0)*2)繼續計算獲得,也就是security1。此時(shí)臨時(shí)表中已經(jīng)有security1的主鍵了,所以count(*)直接加1就可以。
繼續從from的表中取第三條記錄,再次計算floor(rand(0)*2),結果為0,與database()拼接為security0,臨時(shí)表的主鍵中并不存在,在插入前,floor(rand(0)*2)又計算一次,拼接后與secruity1,但是是直接插入,即使臨時(shí)表中已經(jīng)有了主鍵security1也硬要插入,從而導致主鍵重復報錯,也就是:ERROR 1062 (23000): Duplicate entry 'security1' for key 'group_key'。
寫(xiě)到這里報錯的原理已經(jīng)說(shuō)完了,各位觀(guān)眾老爺感覺(jué)呼應上了嗎?
咱們繼續看,咱們共從from的表中取了三條記錄(這也是floor(rand(0)*2)最少需要表中有三條記錄的原因),因為floor(rand(0)*2)的值為011011...,但其實(shí)第三次計算的1可以不要的(變?yōu)?101)。
如果某個(gè)floor(rand(x)*2)滿(mǎn)足0101或1010,那么from 的表中兩條數據就是可以報錯的。我經(jīng)過(guò)多次實(shí)驗,發(fā)現floor(rand(14)*2)的值為101000...,那么咱們創(chuàng )建一個(gè)有兩條數據的表試一下康康。
創(chuàng )建一個(gè)test表,里面只有兩條數據。
分別用rand(0)*2和rand(14)*2做實(shí)驗。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站