今天在DELPHI中用ADO通過ODBC連MYSQL更新數據時遇到這個奇怪的錯誤:無法為更新定位行。一些值可能已在最後一次讀取後已更改。
百思不得其解,於是上網查。有的說是因為沒主鍵,但我這個表是有的;有的說是有缺省值,我檢查了一下,所有字段都是沒缺省值的;有的說是先INSERT再EDIT導致的,我這就是純EDIT、POST,沒有INSERT,所以也不存在。
又找了半天,終於找到類似情況,有人說如果EDIT修改的數據與原有數據一樣,那POST時就會報這個錯誤。我檢查了一下,還真是,我EDIT其實給字段賦的值是跟修改前一樣的,如果稍加改動,字段值有不一樣,就能正常POST提交了。解決辦法只能是給字段賦值前判斷一下值是否相同,真夠BT的。
問題到此算是解決了,但為啥會這樣呢?通過開啟ODBC跟蹤日志進行分析,我們大概能猜到了原因。下面這段是給所有字段賦相同值的SQL跟蹤日志:
BEXE 13f4-1118
EXIT SQLExecDirectW with return code 0 (SQL_SUCCESS)
HSTMT 0x0362C568
WCHAR * 0x0B774FC8 [ -3] "UPDATE `test`.`table1` SET `table1ID`=?,`CONTID`=?,`NAME`=?,...`BKWFID`=? WHERE `table1ID`=? AND `CONTID`=? AND ... AND `BKWFID`=?\ 0"
SDWORD -3
BEXE 13f4-1118 EXIT SQLRowCount with return code 0 (SQL_SUCCESS)
HSTMT 0x0362C568
SQLLEN * 0x0018E804 (0)
注意這時SQLRowCount返回結果是0,意思是更新了0行。
下面這個則是賦值有變化的SQL跟蹤日志:
BEXE 13f4-1118 EXIT SQLExecDirectW with return code 0 (SQL_SUCCESS)
HSTMT 0x0362C568
WCHAR * 0x0B76FEC8 [ -3] "UPDATE `test`.`table1` SET `table1ID`=?,`CONTID`=?,`NAME`=?,...`BKWFID`=? WHERE `table1ID`=? AND `CONTID`=? AND ... AND `BKWFID`=?\ 0"
SDWORD -3
BEXE 13f4-1118 EXIT SQLRowCount with return code 0 (SQL_SUCCESS)
HSTMT 0x0362C568
SQLLEN * 0x0018E804 (1)
這時SQLRowCount返回結果是1,意思是更新了1行。
兩個SQL一模一樣,區別只在於前一個SQL執行後記錄內容沒有變化,而後一個是有變化!然後對於沒變化的情況MYSQL就告訴你,你沒有UPDATE任何記錄,其實你是UPDATE了一條記錄,只是UPDATE前後結果一樣,跟沒有UPDATE的效果相同,於是MYSQL返回了0,於是ADO認為沒UPDATE到數據,於是認為是別人把數據修改掉了,於是就報“無法為更新定位行”的錯誤了。