使用用户定义函数作为表的 DB2 查询结构

发布于 2024-12-02 16:11:38 字数 942 浏览 0 评论 0原文

我对 DB2 有点陌生,在开发查询时遇到困难。我创建了一个用户定义的函数,它返回一个数据表,然后我想在更大的 select 语句中加入并从中选择。我正在处理一个敏感的数据库,所以下面的查询并不是我真正运行的,但它几乎完全一样(没有我必须做的其他 10 个连接,哈哈)。

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  INNER JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35

如果我在不使用 where 子句(或其他不检查 ID 的 where 子句)的情况下运行此查询,则效果非常好。当我包含 where 子句时,出现以下错误:

准备期间出错 58004(-901)[IBM][CLI 驱动程序][DB2/LINUXX8664] SQL0901N 由于非严重系统,SQL 语句失败 错误。可以处理后续的SQL语句。 (原因“糟糕的计划; 发现未解析的 QNC”。)SQLSTATE=58004

我已跟踪问题,发现我正在使用参数的联接标准之一 (B.customerId)。我通过将 B.customerId 替换为有效的 customerId 来验证这一事实,问题是,我在调用此查询时不知道 customerId,我只知道 orderId(在本例中),

因此我只能进行 1 次调用。获取所有信息?我知道计划是问题,因为在调用函数之前 customerId 没有得到解决。

I'm a little new to DB2, and am having trouble developing a query. I have created a user-defined function that returns a table of data which I want to then join and select from in larger select statement. I'm working on a sensitive db, so the query below isn't what I'm literally running, but it's almost exactly like it (without the other 10 joins I have to do lol).

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  INNER JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35

This works great if I run this query without the where clause (or some other where clause that doesn't check for an ID). When I include the where clause, I get the following error:

Error during Prepare 58004(-901)[IBM][CLI Driver][DB2/LINUXX8664]
SQL0901N The SQL statement failed because of a non-severe system
error. Subsequent SQL statements can be processed. (Reason "Bad Plan;
Unresolved QNC found".) SQLSTATE=58004

I have tracked the issue down to fact that I'm using one of join criteria for the parameters (B.customerId). I have validated this fact by replacing B.customerId with a valid customerId, and the query works great. Problem is, I don't know the customerId when calling this query. I know only the orderId (in this example).

Any thoughts on how to restructure this so I can make only 1 call to get all the info? I know the plan is the problem b/c the customerId isn't getting resolved before the function is called.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゞ花落谁相伴 2024-12-09 16:11:38

因此,如果我理解正确,函数 getShippingHistory(customerId) 返回一个表。

如果您使用单个客户 ID 来调用它,则该表会加入到上面的查询中,完全没有问题。

但是按照上面编写的查询的方式,您要求 db2 为查询返回的每一行(即与您的联接和 where 条件匹配的每个 b.customerId)调用该函数。

所以我不确定您期望什么行为,因为您要求的是查询中每一行的表,并且 db2 (我也)可以弄清楚结果应该是什么样子。

因此,在重构查询方面,请考虑当涉及多个客户 ID 时如何更改 getShippingHistory 逻辑。

So if I understand correctly, the function getShippingHistory(customerId) returns a table.

And if you call it with a single customer Id that table gets joined in your query above no problem at all.

But the way you have the query written above, you are asking db2 to call the function for every row returned by your query (i.e. every b.customerId that matches your join and where conditions).

So I'm not sure what behaviour you are expecting, because what you're asking for is a table back for every row in your query, and db2 (nor I) can figure out what the result is supposed to look like.

So in terms of restructuring your query, think about how you can change the getShippingHistory logic when multiple customer Ids are involved.

风吹雨成花 2024-12-09 16:11:38

我发现最好的解决方案(给定当前的查询结构)是使用左连接而不是内连接,以强制连接的左部分发生,这将在到达函数时将 customerId 解析为一个值称呼。

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  LEFT JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35

i found the best solution (given the current query structure) is to use a LEFT join instead of an INNER join in order force the LEFT part of the join to happen which will resolve the customerId to a value by the time it gets to the function call.

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  LEFT JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文