0

我认为我缺少有关使用 SQL 语句和(Delphi 的 ADO)查询组件和/或在(Access 2003)数据库中设置字段之间关系的基本知识。每当我想删除、更新等任何比 SQL.Text="SELECT something FROM aTable" 更复杂的东西时,我都会收到错误消息。

例如,我在名为 Outline 和 Reference 的表之间创建了一个简单的多对多关系。联结或联结表称为注:

Outline
  OutlineID (PK)
  etc.

Reference
  RefID (PK)
  etc.

Note
  NoteID (PK)
  OutlineID
  RefID
  NoteText

我在 Access 中的联接上强制执行参照完整性,但没有勾选复选框以级联删除或更新。同时,在德尔福我的 Query.SQL.Text 是

SELECT Note.NoteID, Outline.OutlineID, Ref.RefID, Note.NoteText, Ref.Citation, Outline.OutlineText
FROM (Note LEFT JOIN Outline ON Outline.OutlineID=Note.OutlineID)
LEFT JOIN Ref on Ref.RefID=Note.RefID; 

最初,我在 SELECT 语句中省略了对键的引用,当我尝试从结果表中删除记录时产生“键列信息不足”错误。我我理解:您必须选择数据库需要执行的任何操作的所有字段。如果它不知道加入了什么,它就不能删除、更新等加入的字段。(这是正确的吗?)

那么,我该如何从这个查询中删除一条记录呢?换句话说,我想 (1) 显示一个显示 NoteText、Citation 和 OutlineText 的网格,(2) 从网格中选择一条记录,(3) 执行一些操作,例如单击 DBNavigator 上的删除按钮,以及 (4) 删除Note 表中与所选记录具有相同 NoteID 和 NoteText 的记录。

4

2 回答 2

2

James L 和 Hendra 都提供了如何做你想做的事的精髓。以下是实现它的一种方法。

procedure TForm1.ADOQuery1BeforeDelete(DataSet: TDataSet);
var
  SQL : string;
begin
  SQL := 'DELETE FROM [Note] WHERE NoteID='+
    DataSet.FieldByName('NoteID').AsString;
  ADOConnection1.Execute(SQL);
  TADOQuery(DataSet).ReQuery;
  Abort;
end;

这将允许 TADOQuery.Delete 正常工作。Abort 是必要的,以防止 TADOQuery 在您删除记录后也尝试删除它。主要缺点是 TADOQuery.ReQuery 不保留光标位置,即当前记录将是第一条记录。

更新:

以下尝试恢复游标。我不喜欢第二个 Requery,但在尝试恢复无效书签后似乎有必要恢复 DataSet(由于删除了最后一条记录)。这适用于我有限的测试。

procedure TForm1.ADOQuery1BeforeDelete(DataSet: TDataSet);
var
  SQL : string;
  bm : TBookmarkStr;
begin
  SQL := 'DELETE FROM [Note] WHERE NoteID='+
    DataSet.FieldByName('NoteID').AsString;
  bm := Dataset.BookMark;
  ADOConnection1.Execute(SQL);
  TADOQuery(DataSet).ReQuery;
  try
    Dataset.BookMark := bm;
  except
    TADOQuery(DataSet).Requery;
    DataSet.Last;
  end;
  Abort;
end;
于 2012-07-29T01:46:36.717 回答
0

如果您使用的是TADOTable,则当您从数据集中删除它们时,组件会处理数据库中的删除TADOTable。但是,由于您使用的TADOQuery是连接多个表的 a,因此您需要以不同的方式处理数据库删除。

当您创建要删除数据库网格中当前记录的记录时,它会将TADOQuery' 的光标滚动到其数据集中的该行。然后您可以使用TADOQuery.Delete删除当前记录。如果您为TADOQuery.BeforeDelete事件编写代码,您可以在本地删除记录之前从记录中捕获 id 字段,并使用另一个TADOQueryTADOCommand组件,您可以创建并执行 SQL 以从数据库中删除记录。

由于删除数据库记录的代码是在BeforeDelete事件中,如果发生异常,数据库记录没有被删除,本地删除也会被取消,本地记录也不会被删除--报错被显示(例如,'外键违规'...)。

于 2012-07-27T17:41:46.403 回答