首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Delphi + dbExpress + MySQL 多層更新「Record not found」錯誤根因與修復

     編輯:MySQL 綜合教學

Delphi 7 + dbExpress 2.0 + MySQL 5.0 環境下,TSimpleDataSet.ApplyUpdates 報錯 Record not found or changed by another user / Unable to find record. No key specified。根因在於 TSimpleDataSet 封裝隱藏了關鍵屬性,導致更新 SQL WHERE 條件包含所有列,任一列被並發修改即失敗。

錯誤現場

  • 更新前 SQL:UPDATE students SET ... WHERE 班級='1' AND 註冊學號='080801031286' AND 身份證號='xxx' ...(所有列)
  • MySQL 返回受影響行數 0(因 WHERE 條件不匹配),MIDAS 判定為「記錄未找到」。

核心原因

  1. TSimpleDataSet 內部 TSQLQuery 的字段 ProviderFlags 默認全包含 pfInWhere,生成全列 WHERE。
  2. 修改 TSimpleDataSet 映射的 TClientDataSet 字段屬性無效,因生成 SQL 時讀取的是 TSQLQuery 層字段屬性。
  3. MySQL ROW_COUNT() 返回實際修改行數而非匹配行數,若 SET 值與原值相同,返回 0,MIDAS 誤判為未找到記錄。

修復方案:棄用 TSimpleDataSet,拆分三層組件

TSQLConnection -> TSQLQuery -> TDataSetProvider -> TClientDataSet -> TDataSource -> DBGrid
  1. TSQLQuery.SQL:SELECT * FROM table
  2. 雙擊 TSQLQuery 添加所有字段,僅主鍵保留 pfInWhere,其餘字段去掉 pfInWhere。
  3. TDataSetProvider.UpdateMode := upWhereKeyOnly(或默認)。
  4. TClientDataSet 寫 AfterPost 執行 ApplyUpdates + 事務提交。

修復後 SQL 對比

-- 修復前:全列 WHERE
UPDATE students SET 曾用名='99'
WHERE 班級='1' AND 註冊學號='080801031286' AND 身份證號='xxx' ...

-- 修復後:僅主鍵 WHERE
UPDATE students SET 曾用名='11' WHERE 註冊學號='080801031285';
UPDATE students SET 曾用名='qq', 父親姓名='aa'... WHERE 註冊學號='080801031286';
COMMIT;

SQL 簡潔、高效、並發安全。

備選方案:調整 Provider.UpdateMode

  • upWhereKeyOnly:WHERE 僅主鍵,需確保客戶端不修改主鍵。
  • 若表無主鍵,在 TSQLQuery/TClientDataSet 字段屬性中將唯一列 ProviderFlags.InKey := True。

架構升級建議

  • 三層組件模式支援無縫遷移:中間層只需替換 TSQLQuery 為 TADOQuery 或移至應用服務器。
  • TSimpleDataSet 僅適合極簡單場景,正式項目強烈建議拆分。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved