我的问题与http://www.delphibbs.com/delphibbs/dispq.asp?lid=538610的相同
问题如下:
   在ADOQuery的SQL中join连接了两个表
   删除、插入ADOQuery的一条记录,只对一个表删除、插入,但是ADO自动把两个表都
删除、插入。怎样才能实现对一个表删除、插入?
其中pclover的答案是:
 ADO是MS的数据解决方案,BORLAND只是做了一下包装,BDE下面的TQuery + TUpdateSQL是非常优秀的
解决方法,但在ADO下面,大致有以下几种方法
(1).用原生ADO的Unique_Table动态属性,外加调用Resync方法解决
(2).不用Joined Query,用LookUp字段,速度稍慢
(3).用可更新视图(用Instead of来保存修改)
(4).用TbetterADOdataSet控件,但是Batch方式下有问题
(5).用TADOUpdDataSet + TADOUpdSQL解决,但要Money.如果第二种可以那就最好了:)
不过我一直没有成功!不知是那里的问题?那位大侠如果成功了能不能把代码贴出来大家参考一下!我认为有效率不要钱的方法就是第三种了,
不过bland的adoquery或adodataset在UpdateBatch时并不去更新视图
而是分为了用两个insert语句分别更新了视图的两个基表,这样在视图的
触发器就不起作用了!
不知大家是怎样解决这个问题的?

解决方案 »

  1.   

    还有一个方法,比较自由.供参考我以前就这样用
    ADOQuery缓存设大一点!
    ADOQuery打开后,将ADOQuery.Connection:=nil;
    当需要保存数据时,检索ADOQuery被修改的数据,
    用ADOCommand与SQL语句直接写表,当需要刷新时,
    再改ADOQuery.Connection,关闭打开一次就行了
      

  2.   

    madyak(无天):
      你这种方法在大数据量提交时速度是会很慢的!
      

  3.   

    你送的是SQL语句,
    对数据库直接操作,
    不会太慢吧
      

  4.   

    不慢!ADOQuery.Connection:=nil后,已与数据库失去连系,所有操作都暂存在本地缓存中
    所以此时操作速度很快!当保存数据时,直接写表,速度也不慢!只是刷新数据时,要仔细一点,
    主要是SQL语句要加上适当的条件,必免每次都存取大量数据!如果并行操作不频繁,其实此时刷新操作不是必需的.因为客户端的修改都能实进的显示!采用这种方式做还有一个好处:没有不能修改的表及视图,包括交叉表也修改,只是真正保存到服务器时,还要算一下,别改错了位置!
      

  5.   

    补充一下:ADO如果按如下设置,会更就好的效果! 
     ADOQuery1.CacheSize:=1000;//可根据需要调整
      ADOQuery1.CursorLocation:=clUseClient;
      ADOQuery1.CursorType:=ctStatic;
      ADOQuery1.LockType:=ltBatchOptimistic;
      

  6.   

    madyak(无天):
      再请问一下,直接写表是对已查出的数据进行循环判断,如果有更改或添加就直接用sql语句去操作相应的表,当刷新时再将数据取出来,是吧?
      

  7.   

    madyak(无天):
      我在按你的方法做测试时遇到一个小问题,如何循环判断一每一条存在的记录是添加的还是更改的呢:)
      

  8.   

    Filters a recordset based on row update status.Delphi syntax:type TFilterGroup = (fgUnassigned, fgNone, fgPendingRecords, fgAffectedRecords, fgFetchedRecords, fgPredicate, fgConflictingRecords);
    property FilterGroup: TfilterGroup;C++ syntax:enum TFilterGroup { fgUnassigned, fgNone, fgPendingRecords, fgAffectedRecords, fgFetchedRecords, fgPredicate, fgConflictingRecords };
    __property TFilterGroup FilterGroup = {read=GetFilterGroup, write=SetFilterGroup, nodefault};DescriptionUse FilterGroup to filter the recordset displayed with an ADO dataset component. The filter requires the dataset be in update batch mode and the rows are filtered based on the update status of individual rows. Set FilterGroup to a TFilterGroup constant to filter the dataset to show just the rows that match that batch update status. For instance, set FilterGroup to fgPendingRecords to show just the rows that have been modified since the last update application.if (ADODataSet1.LockType = ltBatchOptimistic) then begin
      ADODataSet1.Filtered := True;
      ADODataSet1.FilterGroup := fgPendingRecords;
    end;
    if (ADODataSet1->LockType == ltBatchOptimistic)
    {
      ADODataSet1->Filtered = true;
      ADODataSet1->FilterGroup = fgPendingRecords;
    };To use FilterGroup to filter based on the update status of rows, ensure that the LockType property is set to ltBatchOptimistic (a prerequisite for batch updating) and the Filtered property is set to true. In a filtered dataset, check the update status of individual rows using the RecordStatus property.The TFilterGroup type consists of the following constants:Filter group type MeaningfgUnassigned Specifies that no filtering is in effect. This constant is used internally by the ADO dataset component.
    fgNone Removes any current filtering and all rows are visible. Can also be done by setting the Filtered property to false.
    fgPendingRecords Filters to show just the rows that have been changed and the changes have not been applied (UpdateBatch method) or canceled (CancelBatch).
    fgAffectedRecords Filters to show just the rows affected by the last update.fgFetchedRecords Filters to show just the rows in the current update cache. This is the results of the last call to retrieve rows from the database.
    fgPredicate Filters to show just deleted rows.
    fgConflictingRecords Filters to show just the rows that had changes made to them, but could not be applied due to errors on the apply attempt.请参考上面更改表数据时,结合SQL语句(主要是条件)
    相信你可以实现你的目的!
      

  9.   

    madyak(无天):
       多谢你的帮助!我刚试了一下能够利用FilterGroup,oldvalue,newvalue,vale等属性判断出那些被更改、添加,删除掉的数据了,不过这样做还真是要写不少代码,不像我想的一个UpdateBatch方法就可以了:),现在这是最好的答案了!再次感谢madyak(无天)!!
      再等两天如果有没有更好的答案就结束了:)
      我个人觉得如果能使adoquery或adodataset能直接更新视图,不更新基表,那我只要在视图写触发器就可以了,不像亮种方法要在客户端写那么多代码,容易出错:)
      希望有更好的答案出现!!
      

  10.   

    今天做了一个测试,发现我自己写的数据交程序(实现了更改,添加,添加,用2000条数据测试)用时是一万多毫秒,而UpdateBatch函数只要一千多毫秒,慢了十倍!
    跟踪后发现我的程序在执行时多执行了如:SET NO_BROWSETABLE OFF,exec sp_unprepare 77,SET FMTONLY ON exec sp_execute 76 SET FMTONLY OFF这样的语句,而updatebatch 执行时则没有!
    我是用ADOCommand执行sql语句的,如何解决这个问题呢?
    请问madyak(无天),我的自己更新了数据后有没有办法将记录的RecordStatus属性设置为rsOK
      

  11.   

    这一块是比较难弄,我也没什么好办法!
    优化一下ADOCommand的SQL语句,能用;,,,,:s1,:2...' 这种参数型式,再有ADOCommand.Prepared:=True;(或用存储过程)不过太复杂的SQL语句设成ADOCommand.Prepared:=True,还不能正确执行
    要把;,,,,:s1,:2...' 尽量写在SQL前端,不要用在嵌套里,弄不好设不成TRUE!ecordStatus设成OK比较难,本来就没用它写库!实在不行就关闭再打开,刷新一下!
    你自己再想想好办法吧!
      

  12.   

    成功了!!
    我现在测试后与UpdateBatch一样快了,甚至还要快一点:)
    主要是更改了ExecuteOption属性:
    eoAsyncExecute false
    eoAsyncFetch true
    eoAsyncFetchNonBlocking true
    eoExecuteNoRecords          false
      

  13.   

    多谢madyak(无天)了!
    我看现在只有用这种方法了:)
      

  14.   

    to  xiaohewanwan(小何) :
    帮我看看
    http://expert.csdn.net/Expert/topic/1885/1885783.xml?temp=.2757379