【问题标题】:ORA-01417 - Two outer joins error. New join syntax?ORA-01417 - 两个外部连接错误。新的连接语法?
【发布时间】:2019-07-23 10:31:34
【问题描述】:

我从来没有想过“新”SQL 连接语法,因此使用带有 (+) 的“旧”连接系统。我知道是时候学习它了 - 但是我发现旧语法更加直观,尤其是在处理具有多个连接的多个表时。

但是我现在有一个操作需要在同一个表上进行两个外连接。我的代码是:

SELECT
    C.ID,
    R.VALUE,
    R.LOG_ID,
    LOG.ACTION
FROM
    C,
    R,
    LOG
WHERE
    C.DELETED IS NULL
    AND R.DELETED IS NULL
    -- Two joins below
    AND R.C_ID(+) = C.ID
    AND R.LOG_ID(+) = LOG.ID

但是这会导致错误:

ORA-01417 - 一个表最多可以外部连接到一个表。

搜索这个错误我发现解决方案是使用新语法例如这个答案在SO上: Outer join between three tables causing Oracle ORA-01417 error

所以我知道有些人可能会认为这个问题是重复的,因为它在技术上已经有了答案。但是,该问题中提出的“旧”语法不包含与我在这里完全相同数量的表和连接,并且尽我所能尝试,我不确定如何将其纳入我自己的代码中。

有人可以帮忙吗?谢谢。

【问题讨论】:

  • 也许你应该习惯使用超过 25 年的“新”语法,因为它已经在 1992 年的 SQL 标准中。
  • LOG和C之间没有连接条件;是这样吗?
  • 甚至 Oracle 都建议对外部连接使用“新”语法,并停止使用专有的 (+) 运算符。
  • 事实上,旧语法可能是模棱两可的(因为它定义了列上的连接)。新语法不是(因为它定义了表上的连接)
  • 我听到你在进行切换 - 我曾经认为旧方式更容易“计算”,而新方式几乎无法理解,但实际上,一旦我做出切换,它实际上非常简单而合乎逻辑(即使它确实让我对我如何看待连接有不同的心理画面)。我完全建议切换到新语法 - 一开始它更清晰(所有连接条件都与它们正在连接的表一起),并且不太容易出现无意的交叉连接(当你添加连接条件时很容易忘记将它们添加为谓词)。而且新样式更加灵活!

标签: sql oracle join


【解决方案1】:

我想你想要:

SELECT C.ID, R.VALUE, R.LOG_ID, LOG.ACTION
FROM C LEFT JOIN
     R 
     ON R.C_ID = C.ID LEFT JOIN
     LOG
     ON R.LOG_ID = LOG.I
WHERE C.DELETED IS NULL AND
      R.DELETED IS NULL;

“新”(已有 25 年历史)外连接语法实际上很容易理解,尤其是对于仅使用 LEFT JOIN 的简单示例。

这个想法是您希望保留一个表中的所有行(可能受WHERE 子句中的过滤器的影响)。那是第一张桌子。然后使用LEFT JOIN 链来引入其他表。

第一个表中的所有行都在结果集中。如果其他表中有匹配的行,则这些表中的列来自匹配的行。如果没有匹配项,则保留第一个表中的行。

【讨论】:

  • 这是不正确的,(如您所知)每个后续连接都使用前面连接的结果作为其左表,而不是“链”的第一个表。大概你是想说关于一个涉及 FK 的特殊情况,但这不是说。
猜你喜欢
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
相关资源
最近更新 更多