当前位置:网站首页>Automatic conversion of Oracle-style implicit joins to ANSI JOINs using jOOQ
Automatic conversion of Oracle-style implicit joins to ANSI JOINs using jOOQ
2022-08-02 00:32:00 【YYniannian】
虽然jOOQ主要被用作Javaembedded dynamicSQL的内部SQL DSL,It offers the best solution on the market,但jOOQIt is also increasingly being used for one of its secondary functions.在jOOQ 3.9中引入的解析器Mainly to be able to解析DDL语句,For example reverse engineering your schema for code generation purposes,We have added more and more features and SQL转换能力,Enables the parser as a standalone product,通过命令行界面、我们的网站or by ordinaryjOOQ API来使用. 在jOOQ 3.14中增加的一个功能,Mainly for those usejOOQUseful as a profiler,就是将旧的OracleStyle implicit joins are converted to ANSI JOIN的能力.
为什么要避免 "隐式连接"?
大多数RDBMSVendors all support the old onesOraclestyle implicit join syntax,and optimized appropriately.在过去,在SQL-92之前,This is what we use to internally join tables,例如,在查询Sakila数据库时.
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id
AND fa.film_id = f.film_id
复制代码
诚然,This syntax is very intuitive.Just declare all the tables you want to get data from,Then make sure to only filter by matching primary keys/foreign key values to hold the appropriate data. 当然,This can go horribly wrong.For many obvious reasons,例如,When you forget a join predicate after adding a table.If the query is complex,This can be hard to debug.解决方案是ANSI JOIN.从SQL-92开始(差不多30年了!),That's what we are in mostRDBMSconnection in .
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
复制代码
Although it is still possible to define the wrong join predicate,But at least it is no longer possible to forget a predicate,Because this is grammatically incorrect(除了MySQL,遗憾的是,在那里,ON子句是可选的).
SELECT *
FROM actor a
JOIN film_actor fa -- Syntax error
JOIN film f -- Syntax error
复制代码
jOOQ的隐式JOIN
注意,People usually refer to the above syntax as "隐式连接",而JPQL和jOOQAnother one was recycled"隐式连接 "的术语,It is based on foreign key paths,甚至比ANSI SQLThe syntax is less error-prone.使用jOOQ,The above query can be written as follows.
ctx.select(
FILM_ACTOR.actor().asterisk(),
FILM_ACTOR.asterisk(),
FILM_ACTOR.film().asterisk())
.from(FILM_ACTOR)
.fetch();
复制代码
These exist only in the queryto-one的关系路径,will be implicitly appropriateLEFT JOIN
或INNER JOIN
添加到FROM
子句中.It's just normalANSI JOIN之上的便利,而不是替代.
改造Oracle的隐式连接
When you have an old codebase,You want to upgrade and convert all queries to useANSI JOIN时,请使用jOOQ来实现.你可以使用jOOQ的编程功能(如前所述),or free websitewww.jooq.org/translate.在网站上,只需选择 "Oracle风格到ANSI JOIN "选项,Place the following on the leftSQL:输入
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
复制代码
然后......呼啦啦.The output shows the result correctly,不需要的CROSS JOIN,Because one of the join predicates is missing:是的,This tool has been of great help!Let's fix the query entered.Let's fix the query entered:Correct input
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
复制代码
如果你使用OracleThe arcane outer join syntax(+)
(或者SQL Server的*=
,It has been unsupported for a while),这也是可行的.You may have such an input:输入
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
复制代码
呃,哇.又来了!其中一个(+)
The symbol is on the wrong side,That's why we got thisRIGHT OUTER JOIN
.This tool shows again,The old syntax is error-prone.Let's fix it.Correct input
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
复制代码
总结
玩一玩,告诉我们你的想法!
学习的节奏慢一点效果才能更好!希望这篇文章对各位有所帮助!共勉.
边栏推荐
猜你喜欢
随机推荐
CRS 管理与维护
【无标题】
What is it like to trade for a living?
06-SDRAM : SDRAM control module
JSP out.println()方法具有什么功能呢?
go语言标准库fmt包怎么使用
08-SDRAM: Summary
面试高频考题解法——栈的压入弹出序列、有效的括号、逆波兰表达式求值
GetHashCode方法与=
[Solution] Emqx startup under win10 reports Unable to load emulator DLL, node.db_role = EMQX_NODE__DB_ROLE = core
【HCIP】BGP小型实验(联邦,优化)
An Enhanced Model for Attack Detection of Industrial Cyber-Physical Systems
els 方块变形
uni-app项目总结
JSP Taglib指令具有什么功能呢?
信息物理系统状态估计与传感器攻击检测
为什么要使用MQ消息中间件?这几个问题必须拿下
Multidimensional Correlation Time Series Modeling Method Based on Screening Partial Least Squares Regression of Correlation Variables
Grid false data injection attacks detection based on coding strategy
含外部储能的电力系统暂态稳定分布式控制