不懂就問(wèn):SQL 語(yǔ)句中 where 條件后 寫(xiě)上1=1 是什么意思
?程序員在編程過(guò)程中,經(jīng)常會(huì)在代碼中使用到“where 1=1”,這是為什么呢?
SQL注入
初次看到這種寫(xiě)法的同學(xué)肯定很納悶,加不加where 1=1,查詢不都一樣嗎?例如:
查詢出來(lái)的結(jié)果完全沒(méi)有區(qū)別呀。
是的,上面的查詢結(jié)果是沒(méi)有區(qū)別,但是這并不是我們要添加它的目的。我們知道1=1表示true,即永真,在SQL注入時(shí)配合or運(yùn)算符會(huì)得到意向不到的結(jié)果。
例如,當(dāng)我們要?jiǎng)h除客戶名稱為“張三”的記錄,我們可以這樣寫(xiě):
這個(gè)時(shí)候如果在where語(yǔ)句后面加上 or 1=1會(huì)是什么后果?
即:
本來(lái)只要?jiǎng)h除張三的記錄,結(jié)果因?yàn)樘砑恿薿r 1=1的永真條件,會(huì)導(dǎo)致整張表里的記錄都被刪除了。
當(dāng)然這種事我們可千萬(wàn)不能干,也不能讓別人有機(jī)可乘,這里只是為了表述where 1=1的作用之一。
語(yǔ)法規(guī)范
我們?cè)趯?xiě)代碼的過(guò)程中,為了保證語(yǔ)法規(guī)范的時(shí)候,也會(huì)使用到where 1=1。
我們先看下面這段Java代碼:
如果我們不寫(xiě)1=1的話,當(dāng)condition 1為真時(shí),代碼拼接后被執(zhí)行的SQL代碼如下:
很明顯,這里會(huì)出現(xiàn)一個(gè)SQL 的語(yǔ)法錯(cuò)誤:and必須前后都有條件。
有人說(shuō)我直接把where寫(xiě)在if語(yǔ)句里面,我就不寫(xiě)where 1=1。
當(dāng)condition 1為真,condition 2為假時(shí),上面被執(zhí)行的SQL代碼為:
這個(gè)確實(shí)沒(méi)有語(yǔ)法錯(cuò)誤,但是當(dāng)condition 1和condition 2都為真呢?那么SQL語(yǔ)句就變成了這樣:
很明顯這是不符合SQL語(yǔ)法規(guī)范的。
這里寫(xiě)上where 1=1 是為了避免where 關(guān)鍵字后面的第一個(gè)詞直接就是 “and”而導(dǎo)致語(yǔ)法錯(cuò)誤,加上1=1后,不管后面有沒(méi)有and條件都不會(huì)造成語(yǔ)法錯(cuò)誤了。
拷貝表
在我們進(jìn)行數(shù)據(jù)備份時(shí),也經(jīng)常使用到where 1=1,當(dāng)然其實(shí)這兩可以不寫(xiě),寫(xiě)上之后如果想過(guò)濾一些數(shù)據(jù)再備份會(huì)比較方便,直接在后面添加and條件即可。
復(fù)制表結(jié)構(gòu)
有1=1就會(huì)有1<>1或1=2之類的永假的條件,這個(gè)在拷貝表的時(shí)候,加上where 1<>1,意思就是沒(méi)有任何一條記錄符合條件,這樣我們就可以只拷貝表結(jié)構(gòu),不拷貝數(shù)據(jù)了。
1=1的性能問(wèn)題
在MySQL早期的版本中“ where 1=1”可能會(huì)對(duì)有所影響,使用了“where 1=1”的過(guò)濾條件以后數(shù)據(jù)系統(tǒng)就無(wú)法使用索引等查詢優(yōu)化策略,數(shù)據(jù)庫(kù)系統(tǒng)將會(huì)被迫對(duì)每行數(shù)據(jù)進(jìn)行掃描(即全表掃描)以比較此行是否滿足過(guò)濾條件,當(dāng)表中數(shù)據(jù)量較大時(shí)查詢速度會(huì)非常慢。
但在5.6版本(也可能更早幾個(gè)版本)以后這個(gè)問(wèn)題被優(yōu)化了,在寫(xiě)“where 1=1”時(shí),查詢分析器會(huì)將“1=1”處理掉,所以不會(huì)對(duì)查詢?cè)斐尚阅苡绊懀信d趣的小伙伴可以試驗(yàn)一下,反正我試過(guò)了。?