以下是搜索CSDN上多表更新得到的一个答案,但在DataSource组件的OnUpdateData事件中里,如何判断DBGRID里的操作是插入还是更新还是删除?各位大侠帮忙啊~~~~~~~~~~~~
为了说明问题,举个书籍数据库的例子如下:  
一个mdb数据库中有两个数据表:Book和Author。  
Book表中记录的是书籍的信息,字段依次为:BookID、BookName、AuthorID。  
Author表中记录的是作者的信息,字段依次为:AuthorID、AuthorName。  
用TADOQuery+TDataSource+TDBGrid来形成一个数据库维护的demo。并且在TADOQuery的SQL属性中添加如下SQL代码:  
 SELECT  Book.BookName,  Author.AuthorName  
 FROM  Book  INNER  JOIN  Author  ON  Book.AuthorID  =  Author.AuthorID  
但程序修改TDBGrid中任意字段的值后会出现如下错误:  
Project  xxxx.exe  raised  exception  class  EOleException  with  message  '缺少更新或刷新的键列信息。'  Process  stopped.  Use  Step  or  Run  to  continue.  
 
     对于用上面这样的SQL得到的记录集,可以使用下面这样的更新方法:  
 
       在DataSouce组件的OnUpdateData事件中执行以下(伪)代码:  
1)    从DBGrid->SelectedRow->Filed(具体记不清了,总之其中有一个Tfield类型的子对象),从它的OldValue和Value属性中得到改变前后的数据,据此产生一个如下所示的自定义的SQL的UPDATE命令:  
       UPDATE    Book  INNER  JOIN  Author  ON  Book.AuthorID  =  Author.AuthorID  
       SET  Book.BookName  =  'Think  In  C++'  
       WHERE  (  ((Book.BookID)='100')  AND  ((Author.AuthorName)='xxx')  )  
 
2)    执行Cancel,放弃修改在DBGrid中的修改。  
3)    通过TADOConnection组件开始事务处理。  
4)    用一个新的临时创建的TADOQuery组件来执行更新操作,更新用的SQL命令从上面得到。  
5)    结束TADOConnection组件的事务处理。  
6)    执行TADOQuery中的refresh以刷新TDBGrid中的数据。  
 
 
以下是在DataSource组件的OnUpdateData事件中的实现代码:  
       //  从DBGrid得到要修正的字段及值,形成SQL命令,  
       //  并把该命令保存到AnsiString类型的变量SQLCmd中。  
       TADOQuery  *q  =  new  TADOQuery(this);  
       q->Connection  =  adoc;  
       q->SQL->Clear();  
       q->SQL->Add(SQLCmd);  
       //  关闭DBGrid与数据库的连接。  
       DBGrid->DataSource->DataSet->Close();  
       //  执行更新操作。  
       adoc->BeginTrans();  
       q->Close();  
       q->ExecSQL();  
       adoc->CommitTrans();  
       //  重新建立DBGrid和数据库的连接。  
       DBGrid->DataSource->DataSet->Open();  
 
       关键在于:根据TDBGrid中的值来产生一条UPDATE命令,然后在执行,以避免TDBGrid自动执行相关的更新操作,从而抛出  
Project  xxxx.exe  raised  exception  class  EOleException  with  message  '缺少更新或刷新的键列信息。'  Process  stopped.  Use  Step  or  Run  to  continue.  
这样的错误讯息。