如何一次获取对象图?

时间:2009-12-30 10:42:43

标签: database

我正在读一本书,其中作者谈到了一步取出一行+所有链接的父行。就像获取订单+所有项目一样。好吧,听起来不错,但确实如此:我从未见过在SQL中要求的可能性 - 让我们说 - 一个订单+ 100个项目?这个记录集怎么样?我是否会获得包含订单和项目表的合并字段的101行,其中100行具有很多订单字段的NULL值,而一行有很多项值字段的NULL值?这是要走的路吗?还是有更酷的东西?我的意思是......我从来没有听说过将数组放到字段上?

2 个答案:

答案 0 :(得分:3)

一个简单的JOIN可以解决这个问题:

SELECT     o.*
,          i.*
FROM       orders o
INNER JOIN order_items i
ON         o.id = i.order_id

将在order_items中为每一行返回一行。返回的行包含来自orders表的所有字段,并连接到order_items表中的所有字段(非常简单地说,表中的记录是连接的,也就是说,它们是通过记录连接组合而成)

因此,如果订单具有(id,order_date,customer_id)且order_items具有(order_id,product_id,price),则上述语句的结果将包含具有(id,order_date,customer_id,order_id,product_id,price)的记录

您需要注意的一件事是,只要有一个'master'有两个不同的'detail'表,这种方法就会崩溃。让我解释一下。

在orders / order_items示例中,orders是master,order_items是detail:order_items中的每一行都属于,或者依赖于order中的一行。反之亦然:订单表中的一行可以在order_items表中包含零个或多个相关行。连接条件

ON o.id = i.order_id 

确保只合并并返回相关的行(假设数据库允许您省略连接条件,则忽略条件将重新调整两个表中所有可能的行组合)

现在,假设您有一个包含两个详细信息的主服务器,例如,客户为master,customer_orders为detail1和customer_phone_numbers。假设您要检索特定客户以及所有订单及其所有电话号码。你可能想写:

SELECT     c.*, o.*, p.*
FROM       customers                c
INNER JOIN customer_orders          o
ON         c.id                   = o.customer_id
INNER JOIN customer_phone_numbers   p
ON         c.id                   = p.customer_id

这是有效的SQL,它将执行(假设表和列名称已到位) 但问题是,它会给你一个垃圾结果。假设您有两个订单(1,2)和两个电话号码(A,B)的客户,您将获得以下记录:

customer-data | order 1 | phone A
customer-data | order 2 | phone A
customer-data | order 1 | phone B
customer-data | order 2 | phone B

这是垃圾,因为它表明订单1与电话号码A和B以及订单2和电话号码A和B之间存在某种关系。

更糟糕的是,这些结果可能会在记录数量上完全爆炸,严重损害数据库性能。

因此,JOIN非常适合将已知深度项目(客户 - >订单 - >订单_项目)的层次结构“展平”到一个大表中,该表只复制每个明细项的主项。但是提取相关项目的真实图表是非常糟糕的。这是SQL设计方式的直接结果 - 它只能输出规范化表而不重复组。这就是对象关系映射器的存在方式,允许从关系数据库中存储和检索可以具有多个从属对象的从属集合的对象定义,而不会失去作为程序员的理智。

答案 1 :(得分:1)

这通常通过JOIN子句完成。这不会导致很多NULL值,但父行的重复值很多。

另一种选择,如果您的数据库和编程语言支持它,它将在一个连接中返回两个结果集 - 一个选择父行,另一个选择相关行。