【问题标题】:Comparing Tables in Delphi without SQL在没有 SQL 的情况下比较 Delphi 中的表
【发布时间】:2013-04-30 01:50:53
【问题描述】:

我在 Delphi 的 Paradox 数据库中使用表时遇到问题。

我需要比较两个表并验证哪些字段相同,哪些字段不同。最后,两个表的字段必须包含相同的值。

但是,一切都必须在不使用 SQL 的情况下完成,只使用纯 Delphi。

这是目前的代码,但我没有得到预期的结果:

procedure TForm1.Button3Click(Sender: TObject); 
  var  
  s1,s2:string;  
begin  
  Table1.First;  
  while not (Table1.Eof) do  
  Begin 
      s1 := Table1.FieldByName('Campo').AsString; 
      Table2.First; 
      while not (Table2.Eof) do 
      Begin 
          s2 := Table2.FieldByName('Campo').AsString; 

          if (s1 <> s2) then 
          begin 
            Table2.Append; 
            Table2.FieldByName('Campo').AsString := 
                Table1.FieldByName('Campo').AsString; 
          end 
          else if (s1 = s2) then 
          begin 
            Table2.Next; 
          end; 

          Table2.Next; 
      End; 
      Table1.Next;  
  End;
End;

【问题讨论】:

  • 如果您更具体地了解“未获得预期结果”部分,将会很有用。你得到的结果与你的期望有何不同?我在您的代码中没有看到 Table2.PostTable.Append 匹配。
  • 使用此代码时会创建一些重复的字段。我应该把 Table.Append 放在哪里?我已经尝试过了,但出现错误。
  • 永远不要告诉寻求帮助的人错误是什么。我们喜欢猜测。
  • 为什么需要两个相同的表??

标签: database delphi delphi-7


【解决方案1】:

您需要进行两次传递才能将丢失的数据从一张表复制到另一张表中。最简单的方法是只创建一个过程来为您执行此操作,然后调用它两次:

procedure TForm1.CopyData(const Src, Dest: TTable);
var
  CompareVal: string;
begin
  Src.First;
  while not Src.Eof do
  begin
    CompareVal := Src.FieldByName('Campo').AsString;
    if not Dest.Locate('Campo', CompareVal, []) then
    begin
      Dest.Insert;     // Or Dest.Append;
      Dest.FieldByName('Campo').AsString := CopmareVale;
      Dest.Post;
    end;
    Src.Next;
  end;
end;

这样称呼它:

procedure TForm1.Button3Click(Sender: TObject);
begin
  CopyData(Table1, Table2);
  CopyData(Table2, Table1);
end;

如果数据库不是很大,这可以正常工作。如果是,您可以通过在要比较的字段上添加索引来提高性能。请参阅TDataSet.Locate 的 Delphi 帮助,其中包含更多信息和一些指向可能有帮助的其他主题的链接。 (链接是当前的 Delphi 帮助,但该信息大部分也适用于 Delphi 7。)

【讨论】:

  • 这个答案是可以的,但忽略了像主键这样的小问题。如果表格只有一个字段,解决方案会很好,但在现实生活中,这只是部分解决方案(尽管它基于也忽略此类问题的问题)。
  • @No'amNewman:是的。这个问题没有要求对使用数据库进行基础教育(这超出了这里的答案范围)。它询问了一个关于使图示代码工作以获得数据的两个匹配副本的具体问题。没有更多信息,这是唯一可以提供的答案。如果发布者在此之后有不同的要求,则应发布一个新问题来提出该问题。 :-)
  • 如果您知道如何编写平衡线算法,就像我们在编写 COBOL 时一直在做的那样,您真的不需要两次通过... :-) 但您确实需要知道哪些字段被视为键。这些不需要是 rDB 术语中的键,它也适用于顺序数据集。
  • @Marjan:您也可以使用 SQL 更轻松地做到这一点,这已被排除在外。不过,请随意编写 BLA 来回答这个问题。 :-)
  • 不,现在没有胃口来吃 BLA :-)(寒冷正在抑制脑电波)。不过,希望在 SQL 解决方案中获得提示/链接。自从我广泛使用 SQL 并需要阅读基本 CRUD 语句之外的内容以来已经有一段时间了。
【解决方案2】:

通读Table2 的所有记录,并将Table2.FieldByName('Campo').AsString 值放入已排序的TStringList 中。然后遍历Table1 的记录并检查stringList.IndexOf 中的所有Table1.FieldByName('Campo').AsString。当IndexOf 返回-1 时,将记录追加到Table2。切换Table1Table2 并重复。

【讨论】:

  • 非常感谢您的回答。但是有什么方法我不需要使用 TStringList 吗?
  • 没有SQL,没有TStringList——接下来要问的是如何在没有代码的情况下做到这一点。
  • -1。这是错误的解决方案。您有一个具有搜索能力的数据库 - 为什么要将数据移出数据库来完成数据库的设计目的?
  • @KenWhite - 你想进入索引和Locate? - 继续。
  • Locate 不需要索引,如果您不处理非常大的数据库,它也可以正常工作。如果你有很多数据,你应该已经有了索引。无论哪种方式,从数据库移动到TStringList 以与数据库中的值进行比较都是不必要的开销。无论哪种方式,您都可以通过一次源数据;使用TStringList,您有额外的开销将其全部存储在内存中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多