自然连接和内部连接之间的区别是什么?


当前回答

内部连接是这样一种连接,即连接表中的匹配行对于返回的第一个表中的一行是必需的 外部连接是这样一种连接,即对于返回的第一个表中的一行,已连接表中的匹配行不需要 自然连接是一种连接(可以是自然左连接,也可以是自然右连接),它假设连接条件是两个表中同名列匹配的位置

我会避免像使用瘟疫一样使用自然连接,因为自然连接是:

not standard sql [SQL 92] and therefore not portable, not particularly readable (by most SQL coders) and possibly not supported by various tools/libraries not informative; you can't tell what columns are being joined on without referring to the schema your join conditions are invisibly vulnerable to schema changes - if there are multiple natural join columns and one such column is removed from a table, the query will still execute, but probably not correctly and this change in behaviour will be silent hardly worth the effort; you're only saving about 10 seconds of typing

其他回答

SQL在很多方面并不忠实于关系模型。SQL查询的结果不是一个关系,因为它可能有重复名称的列、“匿名”(未命名)列、重复行、空值等。SQL不将表视为关系,因为它依赖于列排序等。

SQL中NATURAL JOIN背后的思想是更容易更忠实于关系模型。两个表的NATURAL JOIN的结果将有按名称重复的列,因此没有匿名列。类似地,提供了UNION对应和EXCEPT对应,以解决SQL在遗留UNION语法中对列排序的依赖。

然而,与所有编程技术一样,它需要纪律才能发挥作用。成功的NATURAL JOIN的一个要求是一致地命名列,因为连接隐含在具有相同名称的列上(遗憾的是,SQL中重命名列的语法很冗长,但副作用是鼓励在基本表和视图中命名列时遵守纪律:)

注意,SQL NATURAL JOIN是等价连接**,但这并不妨碍它的有用性。如果NATURAL JOIN是SQL中唯一支持的连接类型,那么它仍然是关系完整的。

While it is indeed true that any NATURAL JOIN may be written using INNER JOIN and projection (SELECT), it is also true that any INNER JOIN may be written using product (CROSS JOIN) and restriction (WHERE); further note that a NATURAL JOIN between tables with no column names in common will give the same result as CROSS JOIN. So if you are only interested in results that are relations (and why ever not?!) then NATURAL JOIN is the only join type you need. Sure, it is true that from a language design perspective shorthands such as INNER JOIN and CROSS JOIN have their value, but also consider that almost any SQL query can be written in 10 syntactically different, but semantically equivalent, ways and this is what makes SQL optimizers so very hard to develop.

下面是一些语义等价的查询示例(使用常用的零件和供应商数据库):

SELECT *
  FROM S NATURAL JOIN SP;

-- Must disambiguate and 'project away' duplicate SNO attribute
SELECT S.SNO, SNAME, STATUS, CITY, PNO, QTY
  FROM S INNER JOIN SP 
          USING (SNO);                        

-- Alternative projection
SELECT S.*, PNO, QTY
  FROM S INNER JOIN SP 
          ON S.SNO = SP.SNO;

-- Same columns, different order == equivalent?!
SELECT SP.*, S.SNAME, S.STATUS, S.CITY
  FROM S INNER JOIN SP 
      ON S.SNO = SP.SNO;

-- 'Old school'
SELECT S.*, PNO, QTY
  FROM S, SP 
 WHERE S.SNO = SP.SNO;

**关系自然连接不是一种均连接,而是一种投影。——philipxy

NATURAL连接只是特定INNER连接(或“等价连接”)的简短语法,一旦语法被解开,两者都表示相同的关系代数操作。它不是一种“不同类型”的连接,就像OUTER(左/右)或CROSS连接一样。

参见维基百科上的equal -join部分:

自然连接提供了等价连接的进一步专门化。通过比较两个表中在连接表中具有相同列名的所有列,隐式地产生连接谓词。对于每对名称相同的列,生成的连接表只包含一列。 大多数专家都认为天然接头是危险的,因此强烈反对使用。危险来自于无意中添加了一个与另一个列同名的新列……

也就是说,所有的NATURAL连接都可以写成INNER连接(反之则不然)。为此,只需显式地创建谓词——例如USING或ON——并且,如Jonathan Leffler所指出的,选择所需的结果集列以避免“重复”。

快乐的编码。


(NATURAL关键字也可以应用于LEFT和RIGHT连接,同样适用。自然左/右连接只是特定左/右连接的简短语法。)

自然连接:它是两个表中所有列的组合或组合结果。 它将返回第一个表相对于第二个表的所有行。

内部连接:这种连接将工作,除非任何列名将在两个表中same

自然连接是在所有公共列的基础上连接两个表。

Common列:在两个表中具有相同名称的列,并且在两个表中具有兼容的数据类型。 只能使用=运算符

内部连接是在on子句中提到的公共列的基础上连接两个表。

公共列:在两个表中都具有兼容数据类型的列,但不需要具有相同的名称。 您只能使用任何比较运算符,例如=,<=,>=,<,>,<>

mysql> SELECT  * FROM tb1 ;
+----+------+
| id | num  |
+----+------+
|  6 |   60 |
|  7 |   70 |
|  8 |   80 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

mysql> SELECT  * FROM tb2 ;
+----+------+
| id | num  |
+----+------+
|  4 |   40 |
|  5 |   50 |
|  9 |   90 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

内连接:

mysql> SELECT  * FROM tb1 JOIN tb2 ; 
+----+------+----+------+
| id | num  | id | num  |
+----+------+----+------+
|  6 |   60 |  4 |   40 |
|  7 |   70 |  4 |   40 |
|  8 |   80 |  4 |   40 |
|  1 |    1 |  4 |   40 |
|  2 |    2 |  4 |   40 |
|  3 |    3 |  4 |   40 |
|  6 |   60 |  5 |   50 |
|  7 |   70 |  5 |   50 |
|  8 |   80 |  5 |   50 |
.......more......
return 36 rows in set (0.01 sec) 
AND NATURAL JOIN :

    mysql> SELECT  * FROM tb1 NATURAL JOIN tb2 ;
    +----+------+
    | id | num  |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    |  3 |    3 |
    +----+------+
    3 rows in set (0.01 sec)