mysql中update語句的返回結果:1、當數據庫的url中沒有“useAffectedRows=true”參數時,返回匹配行數;2、當數據庫的url中有“useAffectedRows=true”參數時,返回影響行數。
本教程操作環境:windows10系統、mysql8.0.22版本、Dell G3電腦。
mysql中update語句返回什么
update語句的結果到底是匹配行數?還是影響行數?
先說結果:如果數據庫的url為:
jdbc:mysql://gitlab.fzghjx.com:3306/cron
則,返回結果為匹配行數(Rows matched)。
若為:
jdbc:mysql://gitlab.fzghjx.com:3306/cron?useAffectedRows=true
則返回的是影響行數(Changed)。
綜上:
如果url中沒有? useAffectedRows=true? 這個參數,則返回的是匹配行數。如果有,則返回的是影響行數。
如何讓其返回值為受影響(changed)的記錄數呢?
只需在mysql數據連接url參數加useAffectedRows=true即可
jdbc.url=jdbc:mysql://localhost:3306/ssm?useAffectedRows=true
擴展知識:
猜想
如果通過cmd操作mysql的update語句,屏幕上顯示其實是這樣的:
當我想這個問題的時候,第一反應有兩個答案,1,在mysql服務器的返回結果中,進行判斷,如果有這個設置為true,則返回Rows matched的值,如果為false,則返回Changed的值。2,在返回給查詢語句的時候,進行這個值的選擇。
證實
借用一個圖來說明創建connection的整個過程:
(圖摘自:https://blog.csdn.net/c929833623lvcha/article/details/44517245)
當我研究了一段時間之后,我發現,這兩種想法都錯了。具體來看:
我寫了一個簡單的jdbc查詢:
1,建立Connection
根據源碼,追蹤,在mysql建立connection的時候,會將useAffectedRows=true這個參數設置為connection的屬性。
在
Connection?connection?=?DriverManager.getConnection("jdbc:mysql://gitlab.fzghjx.com:3306/cron?useAffectedRows=true",?"root",?"root");
往下追蹤:
繼續:connect方法為:Java.sql.Driver#connect,實現為:com.mysql.jdbc.NonRegisteringDriver#connect
useAffectedRows=true就是在com.mysql.jdbc.NonRegisteringDriver#parseURL方法中讀取,并設置到? Properties props中去的。
再往下:com.mysql.jdbc.ConnectionImpl#getInstance獲取connectiong的實例
這里是一個反射,args為? JDBC_4_CONNECTION_CTOR? ?用到的是JDBC的構造函數:
JDBC的構造函數,是:
public?JDBC4Connection(String?hostToConnectTo,?int?portToConnectTo,?Properties?info,?String?databaseToConnectTo,?String?url)?throws?SQLException?{ ????super(hostToConnectTo,?portToConnectTo,?info,?databaseToConnectTo,?url); }
往上找,是ConnectionImp的構造函數:
(順便提一句:這里設置了事務的隔離級別為2,讀已提交)
在這個構造函數里,將? useAffectedRows的值初始化到connection中去了:
這里有206個屬性要設置,useAffectedRows排在190位(不同的mysql-connect-java版本,位置不一樣)。
設置完成之后:
2,創建MysqlIO
設置完屬性之后,就要創建MysqlIO了:
這里有一個“高可用”的選項,如果是的話,就會創建一個重試的IO鏈接。否則,則創建一個只嘗試一次的IO鏈接,失敗了就不會重試。這個選項,也是在url中,通過設置:autoReconnect=true來開啟的。
3,與msyql服務器握手連接
連接IO過程,其實就是創建一個MysqlIO,然后開始握手:
重點來了:在doHandshake方法中,設置了useAffectedRows的選項:(com.mysql.jdbc.MysqlIO#doHandshake)
這個CLIENT_FOUND_ROWS的值為:
也就是低位的倒數第二位的值進行或操作。如果useAffectsRows,則不會進行或操作。
設置完之后,通過mysqlOutput的socket發送給mysql 服務器:
mysqlOutput來源:在MysqlIO構建的時候創建的。
ok,這是一個簡單的過程。接下來,來看tcp的報文:
4,報文分析:
useAffectedRows=true時:
發送請求給mysql服務器:
mysql服務器的響應:
useAffectedRows=false時:
發送請求給mysql服務器:
mysql服務器的響應:
從以上報文可以看出,useAffectedRows為true和false時,msyql服務器的返回值是不同的。最后jdbc取的返回結果,就是報文中,Affected Rows的值 。直接從msyql的結果中獲取,jdbc只是對結果進行了一些解析和過濾。由此證明,最開始的猜想是錯的。
推薦學習:mysql視頻教程