交叉引用数据使用Delphi中的现有数据库写入文本文件?

时间:2014-05-24 18:45:27

标签: database delphi delphi-7

我试图交叉引用写入文本文件的数据使用现有数据库IE(检查写入文本文件的数据是否已存在于数据库中)。

我已经创建了将用户登录数据(名称和密码)写入文本文件的程序,然后我开始编写一个算法来从文本文件中读取数据,但是我有点卡住了我的名字存储在文本文件的第一行和密码(仅限字符串值)存储在下一行。

我不知道如何检查数据是否已存在于数据库中,是否需要先提取数据库的内容?或者你可以直接与数据库交叉引用它?我已经创建了数据库(UserData.accdb),但我尚未将其链接到表单。这就是我到目前为止所做的:

procedure TForm1.btnclickClick(Sender: TObject);

var
 tRegister      :    TextFile;
 Sline          :    String;
 Sname,SPword   :    String;

begin
  Assignfile(tRegister,'register.txt');

Try
 Reset(tRegister);

 except
   Showmessage('File Register.txt does not exist');
   Exit;
 end;

 While not EOF(tRegister) do
   ReadLn(tRegister,Sline);
     Sname:=Copy(Sline);

      // This is where i want to add code 

      end;



   end;

end.

请不要苛刻我仍然是Delphi的新手:)

1 个答案:

答案 0 :(得分:1)

我从您的问题中了解到,您目前仍在尝试检查数据库中是否存在特定记录。我会非常简短地回答这个问题,因为这个网站上有很多类似的问题可以帮助你充实细节。

然而,您的问题的标题询问"交叉引用数据写入具有现有数据库的文本文件"。从描述中可以看出,您似乎正在尝试协调来自两个来源的数据,并确定哪些匹配,哪些不匹配。我会花更多的时间来回答这个问题,因为我认为这些信息会更有价值。


要检查数据库中的数据,您需要:

  • 您配置为指向数据库的连接组件。
  • 链接到连接组件的查询组件。
  • 查询文本将使用SQL语句从数据库中的特定表中选择行。
  • 我建议您对查询进行参数化,以便专门选择您要查找的行(我将在稍后解释原因。)
  • 注意:您可以使用表组件而不是查询组件,这将更改检查现有行的方式。它具有您不需要编写SQL代码的优势。但编写良好的SQL将更具可扩展性。

上述选项因数据库和您正在使用的组件而异。但正如我所说,已有许多类似的问题。通过一些研究,你应该能够弄明白。

如果您遇到问题,可以提出一个更具体的问题,详细说明您尝试过的内容以及哪些内容无效。 (请记住,这不是免费的"为您的服务做好工作",如果看起来像是您期待的,您会得到反对。 )


协调文本文件和数据库之间的数据:

有几种不同的方法。你选择的那个是完全可以接受的。基本上归结为:

  1. 代表Entry
  2. 中的每个TheFile
  3. ..如果Entry
  4. 中存在TheDatabase
  5. .. ..用Entry
  6. 做点什么
  7. .. ..否则使用Entry
  8. 执行其他操作

    以上步骤易于理解,因此很容易确信算法是正确的。如果Delphi中没有单行代码来实现这些步骤并不重要。作为程序员,您可以创建所需的任何其他功能/程序。 例程的结构保持简单是非常重要的。

    上述任何不能轻易实现的步骤,您需要分解为更小的步骤:2.a。 2.B. ; 3.A. 3.B. 3.C. ;等等(这就是自上而下的设计。)

      

    提示:您希望将所有不同的细分转换为自己的功能和程序。这将使维护您的程序并重复使用已经编写的程序更加容易。

    我将专注于分解第2步。如果您的数据库和文本文件变得非常大,那么如何执行此操作非常重要。例如,您可以实现:每次调用函数检查"如果Entry存在",它会查看数据库中的每条记录。这将非常糟糕,因为如果您的文件中有m个条目,而数据库中有n个条目,那么您将进行m x n次检查。

    记得我说过我解释为什么我建议参数化查询

    设计和编写数据库以管理数据。存储和检索数据是它们的主要功能,因此让它来查找您正在寻找的条目是否存在。例如,如果您编写了查询以将所有条目提取到Delphi应用程序中并在那里搜索:

    • 增加应用程序的内存要求。
    • 但更重要的是,如果没有额外的工作,请将自己暴露在上面提到的m x n问题中。

    使用参数化查询,每次调用if EntryExists(...)时,您都可以更改参数值并有效地要求数据库查找记录。数据库完成工作,并给你一个答案。所以你可以编写你的函数,如下所示:

    function TForm1.EntryExists(const AName: string): Boolean;
    begin
      qryFindEntry.Close;
      qryFindEntry.Parameters.ParamByName('EntryName').Value := AName;
      qryFindEntry.Open;
    
      Result := qryFindEntry.RecordCount > 0;
    end;
    
      

    提示:在数据库中的相应列上定义索引非常重要,否则每次打开查询时,它都会搜索每条记录。

    注意:另一个非常相似的选项是在数据库上编写存储过程,并使用存储过程组件来调用数据库。


    补充意见:

    处理文件的例程硬编码为使用register.txt

    这使得它目前的形式无法重复使用。而是将代码移动到单独的方法中:procedure ProcessFile(AFileName: string);。然后在按钮单击事件处理程序调用:ProcessFile('register.txt');

      

    提示:事实上,将代码批量从事件处理程序中移出到具有适当参数的方法中通常是个好主意。更改事件处理程序以调用这些方法。这样做可以使您的代码更易于维护,测试和重用。

    您的异常处理错误

    这是一种非常糟糕的异常处理方法。

    首先,您不想编写不必要的异常处理。它只会使您的代码膨胀,使其更难以阅读和维护。引发异常时:

    • 程序开始将代码退出到最里面的最终 / 块之外。 (因此,例外情况已经退出您的例程 - 因为您已经添加了代码。)
    • 默认情况下,应用程序异常处理程序将处理未处理的异常(意味着您无法在某处吞下)。默认情况下,这将只显示错误对话框。 (因为你已经添加了代码。)
    • 您的代码所做的唯一更改是向实际引发的消息显示不同的消息。问题是你做了一个不正确的假设。 "文件不存在"并非Reset(tRegister);可能引发异常的唯一可能原因:
      • 该文件可能存在,但必须完全锁定。
      • 该文件可能存在,但您无权访问该文件。
      • 可能存在资源错误,意味着该文件存在,但无法打开
    • 因此,您的异常处理代码所做的唯一事情就是引入一个错误,因为它现在能够隐藏异常的真实原因。这可以使故障排除更加困难。

    如果您想提供有关该例外的更多信息,以下是更好的方法:

    try
      Reset(tRegister);
    except
      on E: Exception do
      begin
        //Note that the message doesn't make any assumptions about the cause of the error.
        E.Message := 'Unable to open file "'+AFileName+'": ' + E.Message;
        //Reraise the same exception but with extra potentially useful information.
        raise;
      end;
    end;
    

    第二个问题是,即使您告诉用户该错误,您也已将此事实隐藏在程序的其余部分中。我们假设您发现了ProcessFile方法的更多用途。你现在有一个例程:

    • 通过电子邮件接收文件。
    • 调用ProcessFile。
    • 然后删除文件和电子邮件。

    如果在ProcessFile中引发异常并且您吞下(处理)它,则上述例程将删除未处理的文件。这显然是不好的。如果您没有吞下该异常,则上述例程将跳过删除步骤,因为该程序正在寻找下一个最终 / 块之外。至少通过这种方式,一旦问题得到解决,您仍然可以记录文件以进行故障排除和重新处理。

    第三个问题是您的异常处理程序正在假设您的例程总是让用户与之交互。这限制了可重用性,因为如果您现在在服务器端应用程序中调用ProcessFile,则会弹出一个对话框,没有人关闭它。

    让未解决的异常由应用程序异常处理程序处理意味着您只需要更改服务器应用程序中的默认应用程序异常处理程序,并且所有异常都可以记录到文件中 - 而不会弹出对话框。