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 條件包含所有列,任一列被並發修改即失敗。
UPDATE students SET ... WHERE 班級='1' AND 註冊學號='080801031286' AND 身份證號='xxx' ...(所有列)TSimpleDataSet 內部 TSQLQuery 的字段 ProviderFlags 默認全包含 pfInWhere,生成全列 WHERE。TSimpleDataSet 映射的 TClientDataSet 字段屬性無效,因生成 SQL 時讀取的是 TSQLQuery 層字段屬性。ROW_COUNT() 返回實際修改行數而非匹配行數,若 SET 值與原值相同,返回 0,MIDAS 誤判為未找到記錄。TSQLConnection -> TSQLQuery -> TDataSetProvider -> TClientDataSet -> TDataSource -> DBGrid
TSQLQuery.SQL:SELECT * FROM tableTSQLQuery 添加所有字段,僅主鍵保留 pfInWhere,其餘字段去掉 pfInWhere。TDataSetProvider.UpdateMode := upWhereKeyOnly(或默認)。TClientDataSet 寫 AfterPost 執行 ApplyUpdates + 事務提交。-- 修復前:全列 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 簡潔、高效、並發安全。
upWhereKeyOnly:WHERE 僅主鍵,需確保客戶端不修改主鍵。TSQLQuery/TClientDataSet 字段屬性中將唯一列 ProviderFlags.InKey := True。TSQLQuery 為 TADOQuery 或移至應用服務器。TSimpleDataSet 僅適合極簡單場景,正式項目強烈建議拆分。