【问题标题】:inner joins in oracleoracle的内部连接
【发布时间】:2010-12-19 04:00:54
【问题描述】:

我在考虑 Oracle 的 SQL 实现中的内连接语法,这似乎有点不一致:

假设您有两个关系loan(loan_number, branch_name, amount) 和borrower(customer_name, loan_number)。 loan_number 是两个表共有的属性。现在,Oracle 为您提供了两种表达内连接的方法:

select * 
from loan, borrower 
where loan.loan_number = borrower.loan_number;

以上语句等价于:

select * 
from loan 
     inner join borrower 
     on loan.loan_number = borrower.loan_number;

但是,当表达交叉连接时,只有一种表达方式:

select * 
from loan, borrower;

以下语句在语法上不正确:

select * 
from loan 
     inner join borrower; 

这是无效的; Oracle 期望子句的 ON... 部分

鉴于内部连接只是一个带有过滤条件的交叉连接,你们认为这是Oracle SQL 实现的不一致吗?我错过了什么吗? 我很想听听其他意见。谢谢。

正如大卫在他的回答中指出的那样,语法是:

select * 
from loan cross join borrower;

即使我不知道上面的语法,我仍然认为它不一致。除了允许没有连接条件的内部连接之外,还可以使用交叉连接关键字。交叉连接实际上是没有连接条件的内连接,为什么不将其表示为没有连接条件的内连接呢?

【问题讨论】:

  • (a) 因为这是 SQL 标准定义它的方式,并且 (b) 因为 CROSS JOIN 不包含不在两个单独表中的信息,所以通常(但不总是)浪费,并且应该需要特殊的语法来调用“浪费”的资源。
  • 正如 Jonathan Leffler 所说,SQL 标准明确定义了交叉连接。您在那里做了一个假设,交叉连接是内部连接的一种特殊形式。
  • @jhartelt 交叉连接和内连接都是笛卡尔积,但内连接过滤了结果。
  • CROSS JOIN 语法用于明确声明您需要笛卡尔积。
  • "inner join without a condition"没有任何意义,因为inner join有条件。你的意思可能是没有过滤的时候是inner join,也就是inner join on true,也就是cross join。

标签: sql database oracle inner-join join


【解决方案1】:

我同意这是不一致的。

但我认为 Oracle 实现是一件好事:

  • 当您进行联接时,您几乎总是希望包含一个过滤条件,因此ON 部分是强制性的。
  • 如果您真的不想有过滤条件(您确定吗?),您必须使用 CROSS JOIN sytax 明确告诉 Oracle。

对我来说,不要 100% 一致是很有意义的 - 这有助于避免你的错误。

【讨论】:

  • 我同意你的看法。交叉连接可能不是用户的意思,所以让他们明确说明他们想要什么。
  • 你不必使用交叉连接,你可以在 1=1 上进行内连接。
【解决方案2】:

SELECT *
FROM Loan
CROSS JOIN Borrower

没有不一致。

【讨论】:

    【解决方案3】:

    Oracle 还支持自然连接语法,它根据共享列名连接两个表。这适用于您的情况,因为两个表都有一个名为 LOAN_NUMBER 的列。

    SELECT *
    FROM Loan
    NATURAL JOIN Borrower
    

    现在,您可以在这种情况下提出相同的论点,即完全没有必要使用关键字 natural 。但是如果我们按照逻辑,我们最终会遇到这样一种情况,即该语句可能是交叉连接或自然连接,具体取决于列名:

    SELECT *
    FROM Loan
    JOIN Borrower
    

    这显然是不可取的,因为将 LOAN.LOAN_NUMBER 重命名为 LOAN_ID 会改变结果集。

    所以,这就是你的答案:消除歧义。

    【讨论】:

    • 您的回答很有道理。但是,如果美学由我决定,我会将交叉连接定义为 select * from loan join borrower 并使用 natural 关键字表示自然连接。
    【解决方案4】:

    这种表示内连接的方式:

    select * from loan, borrower where loan.loan_number = borrower.loan_number;
    

    近 20 年不推荐使用。之所以保留它,是因为它只是一个恰好传达内部连接的有效表达式。我会专注于使用更接近当前标准的版本,最大限度地减少误解和彻底错误的机会。

    【讨论】:

    • Oracle 从 9i 版本开始只支持 ANSI 92 连接语法。那是在 2001 年发布的,距离“近二十年”还差得很远。此外,问题是关于 ANSI 标准的 Oracle 实现中明显的不一致。
    猜你喜欢
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多