当前位置:网站首页>使用jOOQ将Oracle风格的隐式连接自动转换为ANSI JOIN
使用jOOQ将Oracle风格的隐式连接自动转换为ANSI JOIN
2022-08-02 00:05:00 【YYniannian】

虽然jOOQ主要被用作Java中嵌入动态SQL的内部SQL DSL,它提供了市场上最好的解决方案,但jOOQ也越来越多地被用于其次要功能之一。在jOOQ 3.9中引入的解析器主要是为了能够解析DDL语句,例如为代码生成目的对你的模式进行逆向工程,我们已经增加了越来越多的功能和SQL转换能力,使解析器能够作为一个独立的产品,通过命令行界面、我们的网站或通过普通的jOOQ API来使用。 在jOOQ 3.14中增加的一个功能,主要是对那些使用jOOQ作为分析器的人有用,就是将旧的Oracle风格的隐式连接转换为ANSI JOIN的能力。
为什么要避免 "隐式连接"?
大多数RDBMS供应商都支持旧的Oracle风格的隐式连接语法,并进行了适当的优化。在过去,在SQL-92之前,这就是我们用于内部连接表的方式,例如,在查询Sakila数据库时。
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id
AND fa.film_id = f.film_id
复制代码诚然,这个语法是很直观的。只要声明所有你想获取数据的表,然后确保只通过过滤匹配的主键/外键值来保留适当的数据。 当然,这可能会出大错。由于许多明显的原因,例如,当你在添加一个表之后忘记了一个连接谓词。如果查询是复杂的,这可能是很难调试的。解决方案是ANSI JOIN。从SQL-92开始(差不多30年了!),这就是我们在大多数RDBMS中的连接方式。
SELECT *
FROM actor a
JOIN film_actor fa ON a.actor_id = fa.actor_id
JOIN film f ON fa.film_id = f.film_id
复制代码虽然仍然有可能定义错误的连接谓词,但至少不再有可能忘记一个谓词,因为这在语法上是不正确的(除了MySQL,遗憾的是,在那里,ON子句是可选的)。
SELECT *
FROM actor a
JOIN film_actor fa -- Syntax error
JOIN film f -- Syntax error
复制代码jOOQ的隐式JOIN
注意,人们通常把上述语法称为 "隐式连接",而JPQL和jOOQ回收了另一种"隐式连接 "的术语,它是基于外键路径的,甚至比ANSI SQL语法更不容易出错。使用jOOQ,上述查询可以写成如下。
ctx.select(
FILM_ACTOR.actor().asterisk(),
FILM_ACTOR.asterisk(),
FILM_ACTOR.film().asterisk())
.from(FILM_ACTOR)
.fetch();
复制代码仅仅在查询中存在这些to-one的关系路径,就会隐含地将适当的LEFT JOIN 或INNER JOIN 添加到FROM 子句中。这只是在普通ANSI JOIN之上的便利,而不是替代。
改造Oracle的隐式连接
当你有一个旧的代码库,你希望升级并将所有的查询转换为使用ANSI JOIN时,请使用jOOQ来实现。你可以使用jOOQ的编程功能(如前所述),或免费网站www.jooq.org/translate。在网站上,只需选择 "Oracle风格到ANSI JOIN "选项,在左边放置以下SQL:输入
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM
actor a,
film_actor fa,
film f,
film_category fc,
category c
WHERE a.actor_id = fa.actor_id
AND fa.film_id = f.film_id
AND fc.category_id = c.category_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码输出
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM actor a
JOIN film_actor fa
ON a.actor_id = fa.actor_id
JOIN film f
ON fa.film_id = f.film_id
CROSS JOIN (
film_category fc
JOIN category c
ON fc.category_id = c.category_id
)
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码然后......呼啦啦。输出正确地显示了结果,不需要的CROSS JOIN,因为其中一个连接谓词丢失了:是的,这个工具已经帮了大忙!让我们来修正输入的查询。让我们来修正输入的查询:修正输入
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM
actor a,
film_actor fa,
film f,
film_category fc,
category c
WHERE a.actor_id = fa.actor_id
AND fa.film_id = f.film_id
AND f.film_id = fc.film_id -- This was missing
AND fc.category_id = c.category_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码固定输出
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM actor a
JOIN film_actor fa
ON a.actor_id = fa.actor_id
JOIN film f
ON fa.film_id = f.film_id
JOIN film_category fc
ON f.film_id = fc.film_id
JOIN category c
ON fc.category_id = c.category_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码如果你使用Oracle的神秘的外层连接语法(+) (或者SQL Server的*= ,它已经有一段时间不被支持了),这也是可行的。你可能有这样的输入:输入
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM
actor a,
film_actor fa,
film f,
film_category fc,
category c
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
AND f.film_id = fc.film_id(+)
AND fc.category_id(+) = c.category_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码产生这样的输出
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM actor a
LEFT OUTER JOIN film_actor fa
ON a.actor_id = fa.actor_id
LEFT OUTER JOIN film f
ON fa.film_id = f.film_id
LEFT OUTER JOIN (
film_category fc
RIGHT OUTER JOIN category c
ON fc.category_id = c.category_id
)
ON f.film_id = fc.film_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码呃,哇。又来了!其中一个(+) 符号在错误的一边,这就是为什么我们得到这个RIGHT OUTER JOIN 。这个工具再次表明,旧的语法是很容易出错的。让我们来修正它。修正输入
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM
actor a,
film_actor fa,
film f,
film_category fc,
category c
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
AND f.film_id = fc.film_id(+)
AND fc.category_id = c.category_id(+)
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码固定输出
SELECT
a.first_name,
a.last_name,
count(c.category_id)
FROM actor a
LEFT OUTER JOIN film_actor fa
ON a.actor_id = fa.actor_id
LEFT OUTER JOIN film f
ON fa.film_id = f.film_id
LEFT OUTER JOIN film_category fc
ON f.film_id = fc.film_id
LEFT OUTER JOIN category c
ON fc.category_id = c.category_id
GROUP BY
a.actor_id,
a.first_name,
a.last_name
复制代码总结
玩一玩,告诉我们你的想法!
学习的节奏慢一点效果才能更好!希望这篇文章对各位有所帮助!共勉。
边栏推荐
- 链上治理为何如此重要,波卡Gov 2.0又会如何引领链上治理的发展?
- Quick solution for infix to suffix and prefix expressions
- Multi-feature fusion face detection based on attention mechanism
- els block boundary deformation processing
- 图解LeetCode——1161. 最大层内元素和(难度:中等)
- 众筹DAO“枯萎”的缩影:曾拍下《沙丘》未出版手稿的Spice DAO解散
- 07-SDRAM :FIFO控制模块
- The Statement update Statement execution
- 微软电脑管家V2.1公测版正式发布
- Arduino 基础语法
猜你喜欢

PHP从txt文件中读取数据的方法

【三子棋】C语言实现简易三子棋

玩转NFT夏季:这份工具宝典值得收藏

GIF making - very simple one-click animation tool

Double queue implementation stack?Dual stack implementation queue?

如何重装Win11?一键重装Win11方法

08-SDRAM:汇总

面试必问的HashCode技术内幕

【解决】win10下emqx启动报错Unable to load emulator DLL、node.db_role = EMQX_NODE__DB_ROLE = core

使用 Zadig 交付云原生微服务应用
随机推荐
好好活就是做有意义的事,有意义的事就是好好活
面试必问的HashCode技术内幕
What is the function of the JSP Taglib directive?
基于相关性变量筛选偏最小二乘回归的多维相关时间序列建模方法
具有通信时延的多自主体系统时变参考输入的平均一致性跟踪
以交易为生是一种什么体验?
QML package management
含外部储能的电力系统暂态稳定分布式控制
Short video SEO optimization tutorial Self-media SEO optimization skills and methods
Don't know about SynchronousQueue?So ArrayBlockingQueue and LinkedBlockingQueue don't and don't know?
Task execution control in Ansible
bgp 聚合 反射器 联邦实验
08-SDRAM:汇总
【加密周报】经济衰退在加息气氛中蔓延 美联储“放手一搏”?盘点上周加密市场发生的重大事件
security cross-domain configuration
【无标题】
An overview of the most useful DeFi tools
els 方块变形判断。
JSP how to obtain the path information in the request object?
为什么要使用MQ消息中间件?这几个问题必须拿下
