使用 SQL 从 AS400 中提取数据的问题

Posted

技术标签:

【中文标题】使用 SQL 从 AS400 中提取数据的问题【英文标题】:Problem with extracting data from AS400 using SQL 【发布时间】:2020-05-26 08:36:31 【问题描述】:

我正在编写一个 SQL 请求,以使用不同的关系从 AS400 导出数据。 我想这样写以减少时间并提高 ETL 的性能(我的 ETL 中至少有 2900 万行可以使用它)。

SQL:

SELECT  A.x1, A.x2, A.x3, A.x4, A.x5,
        (SELECT B.y1, B.y2, B.y3, C.w1 as w 
        FROM TEST1 AS B inner join TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) 
        where (B.y6 = 2)),
        E.q1

FROM TEST3 AS A
LEFT OUTER JOIN TEST1 AS B ON (A.x6 = B.y7)
LEFT OUTER JOIN TEST4 AS E ON ((A.x6 = E.q2) AND (A.x7 = E.q3))

这个错误我真的需要帮助

我遇到了这个异常:

TITRE:Microsoft Visual Studio HRESULT 异常:0xC0202009 Erreur sur Traitement [来源 [2]]:代码错误 SSIS DTS_E_OLEDBERROR。 Une erreur OLE DB 最重要的产品。错误代码:0x80004005。 取消注册 OLE DB est disponible。来源:« IBMDA400 命令» Hresult:0x80004005 描述:« SQL0412 : Sous-requête non admise, car plus d'une colne résultat 原因 。 . . . . : La sous-requête d'un prédicat doit avoir uniquement une colne résultat concurrent lorsque l'autre opérande du prédicat est une expression simple。 En effet, la sous-requête peut extraire zéro, une ou plusieurs valeurs constituant une liste mais apparaissant dans une seule colne résultat。阙阙。 . . : Modifiez le nombre d'éléments renvoyés par la sous-requête pour qu'il n'y ait qu'une seule colne résultat ou remplacez l'autre opérande du prédicat pour obtenir une liste d'expressions。 »。

【问题讨论】:

根据错误消息,您的子查询 SELECT B.y1, B.y2, B.y3, C.w1 as w ... 有多个列。如果您真的想要所有这些列,您可以使子查询成为外部应用,然后将其列包含在您的主选择中。 问题仍然存在。 我很困惑。 SQL Server 是否在“ibm-midrange”计算机上运行?我认为你的标签是错误的。 是的,已检查。我找到了一个解决方案,但它不是最好的:(SELECT B.y1, FROM TEST1 AS B inner join TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) where ( B.y6 = 2)), (SELECT B.y2 FROM TEST1 AS B 内连接 TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) 其中 (B.y6 = 2)), (SELECT B.y3 FROM TEST1 AS B 内连接 TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) where (B.y6 = 2)), (SELECT C.w1 as w FROM TEST1 AS B 内连接 TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) where (B.y6 = 2)),跨度> 您的子查询(如果有效)与任何外部表都不相关。这似乎是一个更大的问题。并且了解您需要使用 DB2 可以理解的语法,而不是 TSQL 语法。在我看来,您需要将子查询设为派生表并将其加入主查询。我建议您使用 DB2 工具开发您的查询以使查询正确。然后在您的 SSIS 逻辑中使用该查询。 【参考方案1】:

您的错误的原因是子查询返回的列不止一列。 AlwaysLearning 已经说过了。

但下一个问题将是您的子查询返回多行。

除非

SELECT B.y1, B.y2, B.y3, C.w1 as w 
FROM TEST1 AS B inner join TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) 
where (B.y6 = 2)

只返回一行。请注意,子查询没有与外部选择相关的条件。在子查询中使用别名 B 不会将其与外部选择相关联,因为它是在内部选择中重新定义的 FROM TEST1 AS B。这使得别名对子查询来说是本地的,并在子查询的外部选择中隐藏了 B 的使用。如果这不是您想要的,即使是,您也应该始终遵循 SQL 中的简单规则,不要重复使用别名。

【讨论】:

【参考方案2】:

您可以使用“表表达式”来连接额外数据,而不是“标量子查询”。

标量子查询仅限于一行(您的可能返回多行)和一列(您的显然试图返回多于一列)。

例如,你可以这样做:

SELECT  A.x1, A.x2, A.x3, A.x4, A.x5,
        f.y1, f.y2, f.y3, f.w,
        E.q1
FROM TEST3 AS A
LEFT OUTER JOIN TEST1 AS B ON (A.x6 = B.y7)
LEFT OUTER JOIN TEST4 AS E ON ((A.x6 = E.q2) AND (A.x7 = E.q3))
left join (
  SELECT B.y1, B.y2, B.y3, C.w1 as w 
  FROM TEST1 AS B -- you should avoid reusing the same alias B, but OK
  inner join TEST2 AS C ON ((C.w2=B.y4) and (C.w3=B.y5)) 
  where (B.y6 = 2)
) f on 1 = 1 -- what's the join condition? I assume you want all rows to match

编辑以加快查询速度

您正在选择表 A 中的所有行;那一定很慢。然而,由于您的连接是等连接,它们可以从索引中受益匪浅;以下索引可以使您的查询更快:

create index ix1 on TEST1 (y7, x1, x2, x3, x4, x5);

create index ix2 on TEST1 (y6, y1, y2, y3);

create index ix3 on TEST4 (q2, q3, q1);

create index ix4 on TEST2 (w2, w3, w1);

【讨论】:

我已经尝试过这个解决方案并且效果很好。但主要问题是需要很长时间。我想减少这个查询提取数据的时间。这就是为什么我试图避免连接并将它写成子查询。 @houssemeddineayari 您正在从表 A 中选择所有行;那一定很慢。我添加的索引可以大大加快您的查询速度,除非您选择的行太多。实际上,您的查询选择了多少行?

以上是关于使用 SQL 从 AS400 中提取数据的问题的主要内容,如果未能解决你的问题,请参考以下文章

AS400 - 令牌“!”无效

使用 .NET 连接到 AS400

我可以使用 sql 在 AS400 中创建“逻辑文件”吗?

十进制字段在 IBM AS400 的窗口上显示为负数

使用 talend 将数据从 as400 加载到雪花时数据发生变化

无法在 SQL 2019 Linux 上使用 PolyBase 通过 ODBC 查询 AS400