通过DB2 TPC-C基准实现探索SQL
2009-12-23 15:00:09 来源:WEB开发网这是一条 重量级 SQL 语句。接下来我们逐步来分析这个查询:
ITEMLIST 由输入参数组合而成。它包括产品以及每种产品的数量,这是在一个 VALUES 子句中收集到的。对于列表中的所有产品,订单 id、地区和仓库是不变的。
通过使用一个关联连接(correlated join), NEW_OL_LOCAL SQL 表函数逐个处理列表中的每种产品。很快您就可以看到,该函数返回产品的价格、某些元数据和库存信息。
对于不能找到的产品(价格为 NULL),可以将其过滤掉。将产生的表称作 DATA。
将 DATA 中的每种产品插入到 ORDER_LINE 中。
将每种产品的价格、名称、元数据和库存信息返回给用户。
这里有两件有趣的事情。
首先, NEW_OL _LOCAL 表函数实际上一次只返回一行。由于这一层关系,它操作起来更像是一个 用户定义的关系操作符。
另外,正如您后面将会看到的, NEW_OL _LOCAL 表函数实际上是写一个表。这里您看到的是一个连接,内表在其中执行数据库修改。为允许这一点,并使数据库保持一致的状态,DB2 需要确信连接的内表和外表没有冲突;或者,DB2 需要外加一个称作 dam 的临时表,以确保在这个表函数开始处理之前,连接的外表被完全导出。由于这个 SQL 表函数是以 内联 SQL PL 编写的,这是 DB2 用于 SQL PL 的宏语言,因此 DB2 可以看穿这个函数,并得出结论,认为该事务在行为上没有问题,这种情况下不需要 dam。
提到连接的内表和外表之间各种可能的冲突之后,还应该提到的是,在这个函数与 INSERT 操作之间也可能发生类似的问题。为了避免太多的复杂性,DB2 强加了一条简单的规则:除非嵌入在相关的函数里面,否则 UPDATE、DELETE 或 INSERT ( 数据更改操作)不应该出现在连接中。而且, 数据更改操作 也不应该出现在嵌套查询中。
相反, 数据更改操作 应该限制在公共表表达式(CTE,也叫做“WITH 子句”)的顶层 SELECT 或最上面的 SELECT 中。在上述例子中,整个过程是这样的: DATA 执行一个 数据更改操作,并作为 CTE 放在 WITH 子句中。 现在它可以为 INSERT 操作提供数据了。
为什么要有这些规则?让 数据更改操作 留在 WITH 子句中,实际上便强加了一个非常自然的顺序,这样可用于解决冲突。
最后,在这个事务中还暴露了有关 数据更改操作 的另一个更新颖的特性: 那就是 INCLUDE-子句,像任何其他 数据更改语句 一样,INSERT 可以使用这个子句。这个子句允许通过附加额外的列来 扩展 OLD TABLE 或 NEW TABLE 过渡表。这些列只是通过 INSERT 操作搭载的,并且上面的 SELECT 可以访问这些列。在这个例子中,产品价格、名称、数据以及有关库存的数据不是 ORDER_LINE 表的一部分。这些列只是暂时传递、用以返回给用户的。
为什么会这么混乱呢?为什么不从 DATA 选择两次 —— 一次用于 INSERT,一次用于最后的 SELECT? 答案很简单:就像 SORT 一样,TEMP 是一个“4 个字母的单词”。
更多精彩
赞助商链接