将涉及多个表的左外连接从 Informix 重写为 Oracle
Posted
技术标签:
【中文标题】将涉及多个表的左外连接从 Informix 重写为 Oracle【英文标题】:Rewrite left outer join involving multiple tables from Informix to Oracle 【发布时间】:2011-11-03 04:01:49 【问题描述】:如何编写一个与以下 Informix 查询等效的 Oracle 查询?
select tab1.a,tab2.b,tab3.c,tab4.d
from table1 tab1,
table2 tab2 OUTER (table3 tab3,table4 tab4,table5 tab5)
where tab3.xya = tab4.xya
AND tab4.ss = tab1.ss
AND tab3.dd = tab5.dd
AND tab1.fg = tab2.fg
AND tab4.kk = tab5.kk
AND tab3.desc = "XYZ"
我试过了:
select tab1.a,tab2.b,tab3.c,tab4.d
from table1 tab1,
table2 tab2 LEFT OUTER JOIN (table3 tab3,table4 tab4,table5 tab5)
where tab3.xya = tab4.xya
AND tab4.ss = tab1.ss
AND tab3.dd = tab5.dd
AND tab1.fg = tab2.fg
AND tab4.kk = tab5.kk
AND tab3.desc = "XYZ"
正确的语法是什么?
【问题讨论】:
Oracle 的哪个版本?对于 8i 或更早版本,答案会有所不同。 Oracle 8i 已经有 100 年历史了。但是,它不支持连接吗? @GolezTroi - ANSI 样式的外连接仅在 Oracle 9i 或更高版本中受支持。在此之前,Oracle 只有自己的定制语法。 【参考方案1】:每个连接写一个表,像这样:
select tab1.a,tab2.b,tab3.c,tab4.d
from
table1 tab1
inner join table2 tab2 on tab2.fg = tab1.fg
left join table3 tab3 on tab3.xxx = tab1.xxx and tab3.desc = "XYZ"
left join table4 tab4 on tab4.xya = tab3.xya and tab4.ss = tab3.ss
left join table5 tab5 on tab5.dd = tab3.dd and tab5.kk = tab4.kk
请注意,虽然我的查询包含实际的左连接,但您的查询显然没有。
由于条件在哪里,您的查询应该表现得像内部连接。 (虽然我承认我不了解 Informix,所以也许我错了)。
The specfific Informix extension used in the question works a bit differently 关于左连接。除了联接本身的确切语法之外,这主要是因为在 Informix 中,您可以指定外部联接表的列表。这些将被左外连接,连接条件可以放在 where 子句中。请注意,这是对 SQL 的特定扩展。 Informix 还支持“普通”左连接,但您似乎不能将两者结合在一个查询中。
在 Oracle 中不存在此扩展,并且您不能将外连接条件放在 where 子句中,因为无论如何都会执行条件。
那么看看当你将条件移到 where 子句时会发生什么:
select tab1.a,tab2.b,tab3.c,tab4.d
from
table1 tab1
inner join table2 tab2 on tab2.fg = tab1.fg
left join table3 tab3 on tab3.xxx = tab1.xxx
left join table4 tab4 on tab4.xya = tab3.xya
left join table5 tab5 on tab5.dd = tab3.dd and tab5.kk = tab4.kk
where
tab3.desc = "XYZ" and
tab4.ss = tab3.ss
现在,只会返回满足这两个条件的行。当没有找到行时它们不能为真,因此如果 table3 和/或 table4 中没有匹配的行,或者如果ss
在两者中的任何一个中为空,则这些条件之一将返回 false,并且没有行被退回。这有效地将您的外部联接更改为内部联接,因此显着改变了行为。
PS:left join
和 left outer join
是一样的。这意味着您可以选择将第二个表连接到第一个表(左侧)。如果连接的“左”部分中只有数据,则返回行。在 Oracle 中,您还可以right [outer] join
使不是左表而是右表成为前导表。如果任一表中有数据,甚至full [outer] join
都会返回一行。
【讨论】:
谢谢。您的回答让我知道了如何解决我的实际问题OUTER(...)
子句将连接变为左外连接。 (该 Informix 语法不支持任何其他类型的外连接。Informix 的更高版本,如 Oracle 的更高版本,支持 ANSI 连接。)
Oracle 确实支持 LEFT、RIGHT 和 FULL OUTER JOIN。没有 LEFT INNER JOIN 或 LEFT CROSS JOIN 这样的东西。因此 LEFT JOIN 只是 LEFT OUTER JOIN 的缩写。 'OUTER' 关键字是可选的,而 LEFT、RIGHT 和 FULL 关键字是必需的。
你的第一个左连接可以是内部的,因为 where 消除了任何空扩展行。但是由于您只是在猜测条件和连接顺序,因此您最好将 where 测试移至左连接。
@philipxy 好点,即使答案是 8 年 ;-) 所以,为时已晚 8 年,我决定查找(并链接)这个 Informix 语法,结果证明外部连接条件确实应该在 Informix 的 where 子句中。所以我现在已经将条件移动到连接,以匹配所要求的内容。我还添加了第二个 sn-p 来更好地解释数据库之间的差异,因为在 Oracle 中,您确实不应该将左连接条件放在 where 子句中。感谢您的推动!【参考方案2】:
我猜你想要类似的东西
SELECT tab1.a, tab2.b, tab3.c, tab4.d
FROM table1 tab1
JOIN table2 tab2 ON (tab1.fg = tab2.fg)
LEFT OUTER JOIN table4 tab4 ON (tab1.ss = tab4.ss)
LEFT OUTER JOIN table3 tab3 ON (tab4.xya = tab3.xya and tab3.desc = 'XYZ')
LEFT OUTER JOIN table5 tab5 on (tab4.kk = tab5.kk AND
tab3.dd = tab5.dd)
【讨论】:
以上是关于将涉及多个表的左外连接从 Informix 重写为 Oracle的主要内容,如果未能解决你的问题,请参考以下文章