mysql多层开发更新数据问题

2016-08-22 10:21:40来源:http://lioncn.blog.51cto.com/1557898/657239作者:lioncn人点击


问题:开发环境:delphi7se + mysql 5.0.67 + dbexpress 2.0 + mysql50open开发控件:tsimpledataset+datasoure+dbgrid/dbedit权限:mysql已经授权用户有select/update权限.但是如果数据有修改,applyupdates(0)始终报告出错.加入outputdebugstring(pchar(strList)),在view/debug windows/event log中监测到两条错误信息:"Record not found or changed by another user.""Unable to find record. No key specified."解决方法:from http://delphi.ktop.com.tw/board.php?cid=30&fid=66&tid=35255測試的 Form 內放了 TSQLConnection、TSQLQuery、TDataSetProvider、TClientDataSet、TDataSource、TDBGrid、TDBNavigator 各一個TSQLConnection 指定 Connection Name 使它和資料庫連接TSQLQuery 連上 TSQLConnection, 指定 SQL (為最簡單的 SELECT * FROM ...), 然後在TSQLQuery的fields属性中添加所有所有的字段, 除了 PK 不動, 其它的列的 ProviderFlags 去掉 pfInWhere(注意喔, PK 的 pfInWhere 要保持勾選喔, 非 PK 的則去掉)TDataSetProvider 連上 TSQLQueryTClientDataSet 連上 TDataSetProvider, 並撰寫 AfterPost (內容就是資料庫交易和 ApplyUpdate) 及 ReconcileError (呼叫 HandleReconcileError)TDataSource,TDBGrid,TDBNavigater 設好基本屬性..Build 出執行檔後, 執行兩份(A和B), 進行測試...針對同一筆資料, A 先異動(PK不異動), 儲存後, B 異動(不管含不含PK), 可成功的儲存 (A,B都按一下更新鈕, 會發現資料以 B 的為最新)針對同一筆資料, A 先異動(包含PK), 儲存後, B 異動(不管含不含PK), 出現 "Record not found or changed by another user" 訊息按取消, 或者選修正並將PK值改成A所輸入的新PK值, 即可通過原因:众说纷纭.但基本有两点需要注意:引用:"ClientDataSet提交时出现"Record not found or changed by another user"错误提示分析原因可能是找不到更新数据,从网上搜索到大致原因有一下几个方面:1、没有主键2、某些字段不能识别某些提供解决方案也无非是设置DSP的UpdateMode属性,去掉字段的一些默认值这些问题,我仔细检查了一下,感觉不可能存在,仔细分析原因:我更新记录是分两种方式一种是:clientdataset.append;....提交后再更新另外一种是大批量插入表,然后打开数据集更新而第一种方案不存在这个问题,我开始分析第2种方案可能存在的问题。有如下语句:INSERT INTO tableA (field1,field2) SELECTfield1,'' FROM tableb前几天发现ClientDataSet的CommandText用SELECT ''是不能识别的,提示无效的参数我想是不是这个原因造成,所以将''改为' '一些正常。"根据mysql的日志分析,我碰到的是第2种情况,但因为字段众多,修改起来比较麻烦,同时我也不想手工写sql语句.在按照上面的方法修改前datasnap回传的sql语句是 update studentsset 曾用名 = '99'where 班级 = '1' and 注册学号 = '080801031286' and 身份证号 = 'xxx' and 姓名 = '顾xx' and 曾用名 = '' and 性别 = '女' and 民族 = '汉族' and 籍贯省 = '江苏' and 籍贯市县 = 'xxx市' and 家庭地址 = 'xxx路51号2单元702' and 联系电话 = '1335' and 毕业学校 = 'xxx' and 父亲姓名 = '' and 父亲单位 = '' and 母亲姓名 = '' and 母亲单位 = ''可以看到,窗体中所涉及到的所有字段,无论是否修改,全部都回传到mysql,累赘.在按照上面的方法修改后datasnap回传的sql语句是update studentsset 曾用名 = '11'where 注册学号 = '080801031285'update studentsset 曾用名 = 'qq', 父亲姓名 = 'aa', 父亲单位 = 'bbbbb', 母亲姓名 = 'cc', 母亲单位 = 'ddddd'where 注册学号 = '080801031286'COMMIT现在,只涉及到窗体中数值发生修改的字段.两相对比可以看出,后面的sql语句更简单,效率更高.另外老外的说法也有道理,这是mysql非标准sql造成的:As I posted in a reply to this thread in dbexpress, I suspect theposters problem is the fact that MySQL does not follow the standardconvention of returning the number of records affected by an update.Most DBMS's return the number of records found that matched the WHEREclause in the update SQL statement. MySQL doesn't do this. It returnsthe number of records that had data changed by the SQL updatestatement. So, if an update SQL WHERE clause matches one record, butthe UPDATE clause does not actually make changes to the column values(for example SET MyField = '123' and MyField already contains '123'),MySQL returns a RowsAffected count of zero. MIDAS interprets this asan unable to find record error.最终结论:引用"我想, 問題就出在 TSimpleDataSet.李維先生在研討會和著作的書籍中也建議大家使用 TSQLQuery+TDataSetProvider+TClientDataSet 的方式雖然 TSimpleDataSet 一樣是由這三個元件包裝而成, 但許多 Property Method Event 被隱藏了.當修改 TSimpleDataSet 拉出來的 TField 的 ProviderFlags 時, 實際上是修改到了 TClientDataSet 這一層的 TField.ProviderFlags而我們要修改的應該是 TSQLQuery 的 TField.ProviderFlags因此不論你怎麼改, TSQLMonitor 所觀察到的 SQL 語句都不受影響所以建議你棄用 TSimpleDataSet我個人一向不使用 TSimpleDataSet (以李先生的建議是, 對於一些 Simple 的事務, 可交由它處理, 其它的事務還是以分成三元件的撰寫方式為佳)使用 TSQLQuery+TDataSetProvider+TClientDataSet 還有別的好處當要改用 ADO 時, 只要把 TSQLQuery 換成 TADOQuery 即可當要改成三層式時, 只要把 TSQLQuery 和 TDataSetProvider 搬到中間層即可"方法2:(未试过,备用)from http://www.diybl.com/course/7_databases/database_other/200838/103354.html''record not found or changed byanother user'',这个错误是我在做项目时,遇到的问题,找了一些参考才解决。如下:所用的控件有:TDataSetProvider,TADOQuery,TClientDataSet1.当 DataSetProvider.UpdateMode=upWhereAll 时,update时 where 是指定全部字段,比如,你有a、b、c 3个字段,修改了c字段,在app server中修改的命令是update ... set c=新c where a=旧a and b=旧b and c=旧c如果 旧的a、b、c之一 已经被其他人改掉了,那where就找不到合适的记录来修改了。所以报告“记录被其他人修改”,这个问题和“锁定”是无关的。2.当 DataSetProvider.UpdateMode=upWhereKeyOnly 时,update时 where 是指定key字段,比如,你有a、b、c 3个字段,修改了c字段,a是key field在app server中修改的命令是update ... set c=新c where a=旧a (只比较a字段)你的程序应该设计为客户修改不到主键字段的值,这样你的客户只能修改到其他字段的值,其他字段不会出现在where中,就不会出现你说的问题了。(用第2种方法解决,注意如果你的表原来没有主键的,需要双击dataset,添加你的所有field,在有唯一值的field的 ProviderFlasgs 属性里面 InKey 设置为 true (该field必须是有唯一值的,能相当于主键的,也就是能唯一确定该行记录的),TADOQuery,TClientDataSet控件里的唯一值的field字都要设置InKey为true)

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台