-2

我找到了一些教程,但它们仍然给我留下了问题。

让我们以 2 个表的经典示例为例,一个用于客户详细信息,一个用于订单详细信息。

数据库中的customers表有:

  • 一个自动递增的整数customer_id作为主键
  • 客户名称的文本字段
  • 联系方式的文本字段

orders桌子上有 :

  • 一个整数customer_id,它是引用customers表的外键
  • 其他一些东西,比如对一堆项目编号的引用
  • 一个整数order_value,用于存储订单的现金价值

我需要两个数据集组件、两个查询和一个连接。

到现在为止还挺好?还是我已经错过了什么?

现在,教程说我必须将与数据库网格相对应的数据源的 MasterSource 设置为与表相对应orders的数据源,在这种情况下,设置为.customersMasterFieldscustomer_id

还要别的吗?例如,我是否应该将与表Detailfields对应的数据源的查询设置为?customerscustomer_id

我应该使用属性还是参数化查询

好的,至此,我们已经按照经典教程进行操作,可以滚动浏览customersDB 网格,查看 DB 网格中显示的当前客户的所有订单orders。当用户单击customers数据库网格时,我必须关闭();然后打开();orders查询以刷新其相应的数据库网格。

然而,那些教程似乎总是假设一个静态数据库,其中包含永远不会改变的现有内容。

当我问另一个问题时,我举了一个例子,我正在使用命令INSERT INTO orders...,并被告知这是一件坏事,我应该:

  • OrdersQuery.Append();
  • OrdersQuery.FieldByName('customer_id') := [一些值]';
  • OrdersQuery.FieldByName('item_numbers') := [某个值]';
  • OrdersQuery.FieldByName('order_value') := [某个值]';
  • OrdersQuery.Post();

那是对的吗?

我问是因为在我看来,命令将数据放入,而查询只应将其取出,但我可以看到命令没有通过数据源的查询链接到数据库网格。

这是一个选择问题,还是必须使用查询?

如果是这样,我似乎不能在查询中使用简单的 SQL 函数,例如 SUM、MIN< AVG、MAX,而必须将它们移到我的代码中。

如果我必须使用查询,我该如何实现 SQLUPDATEDROP

最后,我可以建立主/细节/细节关系吗?

假设我想要一个第三个 DB 网格,它显示客户所有订单的总数和平均值。它从orders表中获取数据(但不能使用 SUM 和 AVG),每次用户选择不同的客户时,该表都会更新,从而给出主/明细/明细关系。我是否只是将其设置为两个主/从关系?IE,数据库网格,数据源,总订单和平均订单查询仅orders引用并且没有引用customers,即使它确实使用customer_id

在此先感谢您的帮助和澄清。我希望这个问题将来能成为其他人的参考(所以,请随时编辑它)。

4

1 回答 1

2

TLDR:在 SQL 世界中,Master/Detail 是一种古老的东西。

当有些人说“Master Detail”时,他们不会一路走下兔子洞。你的问题表明你确实想要。我想分享一些我认为有帮助的东西,但我认为没有人能真正完整地回答你的问题。

  1. 对于某些人的目的,对于任何两个数据集,主详细信息的最小实现只不过是在主表中当前选定的行发生更改时触发的事件处理程序。然后使用此行过滤明细表数据集中的行,以便只有与主行的主键匹配的行可见。如果您在 Delphi 的 VCL 中的大多数类似 TTable 的对象中正确配置它,这是为您完成的,但即使是不明确支持主/详细配置的数据集也可以以这种方式运行,如果您愿意编写一些事件处理程序和过滤数据。

  2. 在我以前的一位雇主那里,有人发明了一个 Master Detail 控制器组件,它连同一个鲜为人知的 Delphi ADO 组件变体,称为 Kamiak,并且它具有一些只熟悉 BDE-TTable 的人的属性大师细节的时代概念是没有预料到的。这是一项非常聪明的工作,它具有以下特点:

    • 您可以创建一个 ADO 记录集并将其保存在内存中,然后作为一个批处理,一次写入一系列详细信息行,当且仅当主行要存储到磁盘时。
    • 您可以将这些主从关系嵌套到几乎任意深度,因此您可以拥有主、详细信息和子详细信息记录。批量更新用于更新,以回答您问题的这一部分。要处理更新,您需要滚动您自己的 ORM 或 Recordset 层,或者使用预构建的缓存/记录集层。有许多选项,从 ADO 到 Delphi 的各种类似 ORM 的组件,甚至涉及客户端数据集或带有数据泵的公文包模型。
    • 您可以修改数据并将其发布到内存中的暂存区域,并一次刷新所有主行和明细行,或者放弃它们。这允许几乎对象关系级别的持久性管理。

尽管上面的 roll-your-own-ORM 方法看起来很可爱,但它并非没有它的阴暗面。系统中的奇怪错误导致我再也不想使用这种方法。我不想夸大其词,但我是否可以谦虚地建议存在这样的事情,即在主细节兔子洞中走得太远?不要去那里。或者如果你这样做了,意识到你真的在构建一个迷你 ORM,并准备好完成这项工作,其中应该包括一组非常可靠的单元测试和集成测试。即便如此,请注意您可能会发现一些非常奇怪的极端情况,并且可能会发现一些非常邪恶的错误潜伏在您美丽的 ORM/MasterDetail 事物中。

就插入而言,这当然取决于您是构建者还是用户。一个满足于在 VCL 中的任何表类之上构建并且从不想用 SQL 弄脏自己的手的人会认为,如果您不害怕 SQL,那么您的方法是错误的。不过,我想知道那个人将如何处理自动分配的身份主键。我将一个人记录存储在一个表中,然后我需要立即取回该人新分配的 ID,它是一个整数,我现在将使用该整数主键,将我的详细信息行与主行相关联,并且详细行,因此将主行的 ID 整数作为外键引用,因为我的 SQL 数据库构造良好,具有引用完整性约束,并且因为我 已经提前考虑了这一切,不想一遍又一遍地重复,我最终从这里开始,构建一个对象关系映射框架。我希望你能看到你的许多问题有多少可能的答案,这些答案导致了数以亿计或数百万种可能的方法,没有一个是正确的。我碰巧不相信 ORM,而且我认为在你上车之前,安全地离开这辆疯狂的火车。我手工编写我的 SQL 代码,我手工编写我的业务对象,并且我不使用任何花哨的 Master Detail 或 ORM 东西。但是,您可以选择随心所欲地做。导致数以亿计或数百万种可能的方法的答案,没有一个是正确的。我碰巧不相信 ORM,而且我认为在你上车之前,安全地离开这辆疯狂的火车。我手工编写我的 SQL 代码,我手工编写我的业务对象,并且我不使用任何花哨的 Master Detail 或 ORM 东西。但是,您可以选择随心所欲地做。导致数以亿计或数百万种可能的方法的答案,没有一个是正确的。我碰巧不相信 ORM,而且我认为在你上车之前,安全地离开这辆疯狂的火车。我手工编写我的 SQL 代码,我手工编写我的业务对象,并且我不使用任何花哨的 Master Detail 或 ORM 东西。但是,您可以选择随心所欲地做。

在 BDE/dBase/平面文件时代,我将作为“主详细信息”实现的内容,现在我只是简单地实现为主行的查询和详细信息行的第二个查询,当主行更改时,我刷新详细行查询,我根本不使用MasterSourceTTable 对象中的或相关的 Master/Detail 属性。

于 2013-03-13T02:21:54.100 回答