Oracle语法转H2语法:(+)连接表

4

我有一个关于 Oracle 的查询如下:

   SELECT DISTINCT count(pa.payment_id)   FROM
    location c,    inventory e,
    inventory_stock es,    payment_client ep,
    payment pa,    currency cur,
    location s,    exchange_country exc,
    exchange_rate sso,
    exchange_hike so,
    exchange_margin sov  WHERE
    cur.outState = 'N' AND
    c.location_id = e.location_id AND
    e.inventory_id = ep.inventory_id AND
    e.inventory_stock_id = es.inventory_stock_id AND
    ep.client_id = pa.end_client AND
    pa.cur_id = cur.cur_id AND
    cur.location_id = s.location_id AND
    c.client_id  is not null  AND
    cur.cur_id = exc.cur_id(+) AND
    exc.exchange_id = sso.exchange_id(+) AND
    sso.account_id = so.account_id(+) AND
    so.option_name(+)  = 'PREMIUM' AND
    exc.exchange_id = sov.exchange_id(+) AND
    sov.name(+)  = 'VALUE';

我现在正在使用H2数据库,我遇到的语法错误来自so.option_name(+)sov.name(+);。我知道 (+) 是Oracle中右连接和左连接的方式,但是否有可能将其转换为H2,使得错误和语法等价?


我已经尝试使用纯连接进行转换,但输出不同。对所有表使用联接太混乱了。 - logger
2
是的,您可以将其转换为适当的“左连接” - 在Oracle中也应该这样做。即使Oracle也建议使用“左连接”(或“右连接”)而不是专有的“(+)”运算符。 - user330315
http://stackoverflow.com/q/23762963/330315 - user330315
http://stackoverflow.com/questions/24852067/convert-oracle-outer-join-to-sql-server - user330315
1个回答

4
现在是时候向前迈进了。Oracle不再推荐使用传统的外连接语法。从官方文档可以看到:

Oracle 建议您使用FROM子句的OUTER JOIN语法,而不是 Oracle 连接操作符。使用 Oracle 连接操作符 (+) 的外连接查询受到以下规则和限制的约束,这些约束不适用于 FROM 子句 OUTER JOIN 语法 [...]

如果您将 (+) 替换成 outer join,那么不仅可以在 Oracle 和 H2 上运行您的查询,还可以大大提高您的应用程序水平。
SELECT DISTINCT count(pa.payment_id) 
FROM location c
JOIN inventory e ON c.location_id = e.location_id
JOIN payment_client ep ON e.inventory_id = ep.inventory_id
JOIN inventory_stock es ON e.inventory_stock_id = es.inventory_stock_id
JOIN payment pa ON ep.client_id = pa.end_client
JOIN currency cur ON pa.cur_id = cur.cur_id
JOIN location s ON cur.location_id = s.location_id
LEFT JOIN exchange_country exc ON cur.cur_id = exc.cur_id
LEFT JOIN exchange_rate sso ON exc.exchange_id = sso.exchange_id
LEFT JOIN exchange_hike so 
  ON sso.account_id = so.account_id
  AND so.option_name = 'PREMIUM'
LEFT JOIN exchange_margin sov 
  ON exc.exchange_id = sov.exchange_id
  AND sov.name = 'VALUE'
WHERE c.client_id IS NOT NULL
AND cur.outState = 'N'

(+)转换为LEFT JOIN时,重要的是要注意哪些谓词必须进入ON子句,哪些谓词在WHERE子句中是可以的。特别是以下两个谓词必须进入相关联的左连接表的ON子句:
  • so.option_name(+) = 'PREMIUM'
  • sov.name(+) = 'VALUE'

第三方工具

您可以使用jOOQ的在线SQL翻译器在语法之间进行翻译,或直接使用jOOQ将Oracle连接的表列表翻译成ANSI连接

免责声明:我为jOOQ背后的公司工作


这个 Github 问题建议 H2 不支持全外连接,因此语句“你的查询将在 Oracle 和 H2 上都可以工作”让我感到困惑。 - Felk
@Felk:我的回答没有使用全外连接,也不支持“(+)”语法...那么,你到底是什么困惑呢? :) - Lukas Eder
是的,抱歉。我没有注意到“outer join”隐含地意味着左外连接。 - Felk
@Felk:哦,我明白你的意思了。实际上,从技术上讲,Oracle的文档并不完全准确。 - Lukas Eder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接