【问题标题】:Query a SQL Database & Edit the found data set查询 SQL 数据库并编辑找到的数据集
【发布时间】:2015-08-30 18:59:52
【问题描述】:

我知道这个问题可能在我无法开始之前就被问到了。我将我的 SQL 设置为有两个表,但在这种情况下,我只会使用一个名为“Book”的表。它有各种列,但我想使用的列是“WR”、“Customer”、“Contact”、“Model”、“SN”、“Status”、“Tech”、“WDone”和“IN”。

我想在名为edtWR 的编辑框中输入文本,并且我希望按钮btnSearch 搜索“WR”列,直到找到匹配项(所有条目都会不同)。一旦它必须将“客户”、“联系人”、“型号”、“SN”、“状态”写入标签,让我们称它们为lblCustomerlblContactlblModellblSN&lblStatus

一旦该人确认这是他们想要的“WR”,就必须在编辑框和一份名为edtTechmmoWDoneedtIN 的备忘录中输入文本,然后单击btnUpdate。然后应该更新该记录。

我有 3 个名为 dtbOut 的 ADO 连接,这是我的 ADOConnection1,tableOut 这是我的 ADOTable,dataOut 是 ADODataSet。如果有帮助,dataOut 的命令文本是 Select * From Book

我可以让整个过程在 access 数据库上完美运行,但我几乎没有 SQL 经验,我需要帮助。我会添加Access数据库的代码以备参考。

 procedure TFOut.btnSearchClick(Sender: TObject);
 begin
     dataout.Filter := 'WR = ''' + 'WR ' + edtwr.Text + '''';
     dataout.Filtered := True;
     dataout.First;

     lblcustomer.Caption := 'Customer: ' + dataout.FieldByName('Customer').AsString;
     lblcontact.Caption := 'Contact: ' + dataout.FieldByName('Contact').AsString;

     lblSN.Caption := 'SN: ' + dataout.FieldByName('SN').AsString;
     lblModel.Caption := 'Model: ' + dataout.FieldByName('Model').AsString;
     lblstatus.Caption := 'Status: ' + dataout.FieldByName('Status').AsString;


procedure TFOut.btnUpdateClick(Sender: TObject);
begin
   dataout.Edit;
   dataout.FieldByName('Tech').AsString := edtTech.Text;
   dataout.FieldByName('WDone').AsString := mmoWDone.Lines.GetText;
   dataout.FieldByName('IN').AsString  := edtIN.Text;
   dataout.Post;
end

我是否需要表单上的任何其他组件才能在 SQL 中执行此操作,我需要什么以及如何开始。我读了很多东西,看来我需要得到一个ADOQuery1,但是当谈到ADOQuery1.SQL 部分时,我会掉下来。我也尝试过 Access 方式,我可以搜索,但是一旦我尝试更新,我就会收到“用于更新或刷新的键列信息不足”错误,我也不知道如何解决。

如果我需要另外说明问题,请说明如何更改以使其更清楚,如果我需要在整个说明或代码中添加任何内容,请告知我。

【问题讨论】:

  • 为什么不使用 TDBEdit、TDBMemo 和 TDBText 等数据感知组件,而不是 TEdit、TMemo 和 TLabel 组件?
  • 我没有使用数据感知组件。它只是普通的 TEdit、TMemo 和 TLabels 组件。是什么让您想到它的数据感知组件? @MartynA
  • 感谢编辑@marc_s
  • “我没有使用数据感知组件。”我知道,这就是我问你为什么不使用它们的原因,因为它们会自动处理诸如将数据集字段值来回复制到它们的 GUI 表示的事情。通常没有理由在代码中这样做。
  • 如果我是你,我会把这个项目放在一边,看看无数在线 Delphi 数据库教程中的任何一个,例如delphi.about.com/od/database/a/databasecourse.htm 了解 DB 感知控件如何为您节省大量编码,并在初学者往往不擅长的地方做正确的事情。顺便说一句,对于初学者来说最有指导意义的 db-aware 组件是 TDBNavigator,因为它有助于可视化 Delphi 的 TDataSet 模型的状态特性,这是 DB-aware 组件的操作所基于的。

标签: sql delphi


【解决方案1】:

SO 并不是提供数据库教程的地方,所以我不打算 尝试一个,而是专注于一件基本的事情,在你开始之前理解并正确地进行数据库设计是至关重要的 编写一个 Delphi 数据库应用程序。 (我将讨论这个问题 Sql Server,而不是 MS Access。)

您提到收到错误“用于更新或刷新的关键列信息不足”,您说您不知道如何解决。

Delphi 数据集(任何类型的,不仅仅是 ADO 数据集)通过维护一个逻辑游标来运行,该游标恰好指向数据集中的一行。当您打开(非空)数据集时,此光标指向数据集中的第一行,您可以使用各种 TDataSet 方法移动光标,例如 Next & PriorFirstLastMoveBy。一些(但不是全部)类型的 TDataSet 实现了它的Locate 方法,该方法使您能够转到与您指定的标准匹配的行,其他类型则不是。 Delphi 的 ADO 组件确实实现了Locate(顺便说一句,Locate 对您已经从服务器检索到的行进行操作,而不是在服务器上查找行)。

TAdoQuery 等面向 Sql 的 TDataSet 的关键思想之一是您可以让它自动生成 Sql 语句来执行更新、删除和插入。这不仅有助于提高生产力,而且在您尝试自己编写代码时避免了编码错误和遗漏。

如果您观察到 ADO 使用 SS 的 Profiler 实用程序针对 MS Sql Server 表执行其操作,然后使用设计良好的数据库,您会发现它非常好且有效地执行此操作提供数据库设计遵循一个基本规则,即必须有一种方法来唯一标识表中的特定行。最常见的方法是在每个表中包含一个 int(eger) ID 列,通常作为第一列,并将其定义为表的“主键”。尽管还有其他方法可以生成合适的 ID 值以放入此列,但 Sql Server 具有特定的列类型“Identity”,它会在服务器上处理此问题。

一旦表有这样的列,ADO 层(这是 Windows 提供的数据访问层,TAdoQuery 等数据集组件位于其上)可以自动生成 Sql 语句来执行更新和删除,例如

Delete from Table1 where Table1ID = 999

Update Table1 set SomeCharField = 'SomeValue' where Table1ID = 666

您可以将其留给 AdoQuery 从服务器获取新插入的行的 ID 值。

让 Sql 自动生成的一个有用方面是它确保 Sql 只影响单行,因此避免影响超出您预期的行数。

一旦您正确掌握了数据库设计的这个关键方面,您会发现 Delphi 的 TDataSet 后代(例如 TAdoQuery 及其 DB 感知组件)可以处理大多数简单的数据库应用程序,而无需编写任何 Sql 语句全部更新、插入或删除 行。但是,通常您仍然需要编写 Sql 语句来从服务器检索您想要的行,方法是使用“Where”子句将检索到的行限制为服务器上行的子集。

也许您的下一步应该是阅读参数化 Sql 查询,以减少您对“Sql Injection”的暴露:

https://en.wikipedia.org/wiki/SQL_injection

因为最好养成使用参数编写 Sql 查询的习惯。顺便说一句,Sql Injection 不仅仅是 Sql 在通过 Internet 发送时被拦截和修改:在某些注入形式中,知道自己在做什么的恶意用户可以简单地在应用程序“期望的地方”键入一些额外的 Sql 语句" 他们只是将某些列值指定为搜索条件。

【讨论】:

  • 谢谢。我现在设法让它继续下去。除了白天工作和晚上编码之外,我将按照建议阅读有关数据感知组件和 sql 的信息。谢谢。最后一件事,Access 自动创建了 ID 字段。因此,我也设法在 SQL 数据库中获得了一个,但是访问会自动为每个新记录地址创建数字,我必须手动将其添加到 SQL 中。我知道我做错了什么,这是一个快速的解决方案吗?如果没有,我会阅读您的建议并稍后解决。 @MartynA
  • 如果您在谈论您的 btnUpdateClick 方法,首先要做的是检查您的 TAdoDataSet 的 IndexFieldNames + IndexFields 属性。其中一项或多项应包括您希望行按 表的 ID 字段排序的字段/列名称。试试看,如果您仍然卡住,请专门(且仅)发布一个新的 q。
  • 感谢一百万。明天下班后我再看看。 @MartynA
猜你喜欢
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-30
  • 1970-01-01
  • 2014-06-07
相关资源
最近更新 更多