TADOQuery

为了说明问题,举个书籍数据库的例子如下:
一个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.
这样的错误讯息

你可能感兴趣的:(query)