原來的sql語句如下:
update `credit_bill` set receipt_no = 'DD-20181022-89757' where receipt_no = 'DD-20181022-316736';
該sql正常執行。
變化後的sql語句如下:
update `credit_bill` set receipt_no = 'DD-20181022-89757 where receipt_no' = 'DD-20181022-316736';
此時引號錯位了,執行結果也變了。執行結果變成,把表中所有的記錄的receipt_no字段的值都更新成了0。
很神奇,但究竟是如何產生這樣的結果的呢,mysql內部又是如何轉義的呢?
轉義後的sql語句變成了這樣:
update `credit_bill` set receipt_no = ('DD-20181022-89757 where receipt_no' = 'DD-20181022-316736');
注:如果把括號提前,變成這樣:
update `credit_bill` set (receipt_no = 'DD-20181022-89757 where receipt_no') = 'DD-20181022-316736';
是會報錯的,語法錯誤。
執行上面的sql,先執行括號內的語句,其實等同於:
select 'DD-20181022-89757 where receipt_no' = 'DD-20181022-316736';
其查詢結果爲0,所以整條sql語句就等同於:
update `credit_bill` set receipt_no = 0
謎底揭開。
補充:
以上情況類似的select語句如下:
select * from credit_bill where receipt_no = 'xxx' = 'yyy';
等同於:
select * from credit_bill where (receipt_no = 'xxx') = 'yyy';
執行時,括號內的語句查詢出來等於0或1。然後比較其結果和字符串'yyy'。
等號一邊是int,一邊是字符串,兩邊會都轉成float進行比較。
'yyy'轉成浮點型值爲0。如果左邊也是0,那麼就等同於0和0比較,而0恆等於0。
所以原sql等同於select * from credit_bill where 1=1;