2

这个问题来自我对 CJ Date's SQL and Relational Theory: How to Write Accurate SQL Code and looking up about joins on the internet(其中包括在 NATURAL JOINs 上遇到多个帖子(以及关于 SQL Server 缺乏对它的支持)的阅读)

所以这是我的问题...

一方面,在关系理论中,自然连接是唯一应该发生的连接(或者至少是高度优选的)。

另一方面,在 SQL 中,建议不要使用 NATURAL JOIN 而是使用替代方法(例如带限制的内部连接)。

是这些的和解:

  • 自然连接在真正的 RDBMS 中工作。然而,SQL 无法完全再现关系模型,而且流行的 SQL DBMS 都不是真正的 RDBMS。

和/或

  • 好的/更好的表设计应该消除/最小化自然连接产生的问题。

?

4

4 回答 4

6

首先,理论与实践之间的选择是一种谬误。引用 Chris Date 的话:“事实是,理论——至少我在这里谈论的理论,即关系理论——确实非常实用”。

其次,考虑自然连接依赖于属性命名。请(重新)阅读Accurate SQL Code book的以下部分:

6.12。对属性名称的依赖。重点引述:

关系代数的运算符……都严重依赖属性命名。

3.9. SQL 中的列命名。重点引述:

强烈建议:……如果 SQL 中的两列代表“相同类型的信息”,请尽可能为它们命名。(这就是为什么,例如,供应商和零件数据库中的两个供应商编号列都称为 SNO,而不是,比如说,一个表中的 SNO 和另一个表中的 SNUM。)相反,如果两列表示不同类型的信息, 给它们起不同的名字通常是个好主意。

我想解决@kuru kuru pa 的观点(也是一个很好的观点)关于将列添加到您无法控制的表中,例如“您正在使用的网络服务”。在我看来,使用第 3.9 节中 Date 建议的策略(上面引用过)有效地缓解了这个问题:引用:

  • 对于每个基表,定义一个与该基表相同的视图,除了可能对某些列进行重命名。
  • 确保如此定义的视图集遵守上述列命名规则。
  • 根据这些视图而不是基础基表进行操作。

就个人而言,我发现“自然加入被认为是危险的”态度令人沮丧。不希望听起来自以为是,但我自己的命名约定遵循ISO 11179-5 命名和标识原则的指导,导致架构非常适合自然连接。

可悲的是,我专业使用的 DBMS 产品(SQL Server)可能不会很快支持自然连接:Microsoft Connect 上的相关功能请求 目前已关闭为“无法修复”,尽管目前有可观的 +38 / - 2 分数 已重新开放并获得了可观的 46 / -2 分数(现在就投票吧:)

于 2011-09-14T08:12:53.763 回答
6

关于您的问题的几点(即使我担心我并没有真正回答您提出的任何问题),

“一方面,在关系理论中,自然连接是唯一应该发生的连接(或者至少是高度首选的)。”

这似乎表明您将理论解释为好像它禁止“其他类型”的连接......这不是真的。关系理论并没有说“你不能有反连接”,或者“你永远不应该使用反连接”,或者类似的东西。它所说的是,在关系代数中,可以识别一组原始运算符,其中自然连接是唯一的“类连接”运算符。所有其他“类似连接”的运算符,总是可以用定义的原始运算符等价地表示。例如,笛卡尔积是自然连接的特例(其中公共属性集为空),如果您想要两个表的笛卡尔有一个共同的属性名称,您可以使用 RENAME 来解决这个问题。例如,半连接是第一个表与第二个表的一些投影的自然连接。Antijoin,例如(Date 书中的 SEMIMINUS 或 NOT MATCHING),是第一个表和两者的 SEMIJOIN 之间的关系差异。等等等等

“另一方面,在 SQL 中,建议不要使用 NATURAL JOIN 而是使用替代方法(例如,带限制的内部连接)。”

哪里有这样的建议?在 SQL 标准中?我真的不这么认为。区分由 ISO 标准定义的 SQL 语言本身和由某个特定供应商构建的该语言的某些(/任何)特定实现非常重要。如果 Microsoft 建议其客户不要在 SQL Server 200x 中使用 NJ,那么该建议的含义与有人建议不要在 SQL 中完全使用 NJ 的含义完全不同。

“自然联接在真正的 RDBMS 中工作。然而,SQL 无法完全复制关系模型,并且没有一个流行的 SQL DBMS 是真正的 RDBMS。”

虽然 SQL 本身确实未能忠实地遵守关系理论,但这实际上与 NJ 的问题几乎没有关系。

一个实现是否为调用 NJ 提供了良好的性能,是该实现的一个特征,而不是语言的特征,也不是“RDBMS”中“R”的“真实度”的特征。构建一个不使用 SQL 的 TRDBMS 非常容易,这给 NJ 带来了荒谬的执行时间。SQL 语言本身具有支持 NJ 所需的一切。如果一个实现支持 NJ,那么 NJ也将在该实现中工作。它是否提供了良好的性能,是该实现的一个特征,并且某些特定实现的较差性能不应该被“推断”到其他实现,或者被视为 SQL 语言本身的一个特征。

“好的/更好的表设计应该消除/最小化自然连接产生的问题。”

自然连接产生的问题?通过在所需列上添加显式投影(并在需要时重命名),可以轻松控制出现在连接参数中的列。就像您也想尽可能避免 SELECT * 一样,出于基本相同的原因......

于 2011-09-14T22:46:04.533 回答
2

SQL 中 NATURAL JOIN 语法的主要问题是它通常过于冗长。

在教程 D 语法中,我可以非常简单地将自然连接编写为:

R{a,b,c} JOIN S{a,c,d};

但在 SQL 中,SELECT 语句需要派生表子查询或 WHERE 子句和别名来实现相同的目的。这是因为单个“SELECT 语句”实际上是一个非关系的复合运算符,其中组件操作总是以预定的顺序发生。投影出现连接之后,连接结果中的列不一定具有唯一的名称。

例如,上面的查询可以用 SQL 写成:

SELECT DISTINCT a, b, c, d
FROM
(SELECT a,b,c FROM R) R
NATURAL JOIN
(SELECT a,c,d FROM S) S;

或者:

SELECT DISTINCT R.a, R.b, R.c, S.d
FROM R,S
WHERE R.a = S.a AND R.c = S.c;

人们可能会更喜欢后一个版本,因为它更短且“更简单”。

于 2011-09-14T15:58:15.583 回答
-2

理论与现实...

自然连接是不实用的。
据我所知,不存在纯粹的(即实践与理论相同)RDBMS。

我认为 Oracle 和其他一些公司实际上支持自然连接——TSQL 不支持。

考虑一下我们生活的世界——两个表都有一个具有相同名称的列的可能性非常高(比如可能是 [name] 或 [id] 或 [date] 等)。也许通过仅对您可能真正想要加入的那些表进行分组来缩小这些机会。但无论如何,如果不仔细检查表结构,您将不知道“自然连接”是否是一个好主意。即使是这样,在那一刻,可能不会在另一年应用程序获得升级,将列添加到某些表等,或者您正在使用的 Web 服务添加了您不知道的字段,等等

我认为一个“纯”系统必须至少是一个你可以 100% 控制的系统,然后是一个在 alter table/create table 过程中会有一些很好的验证的系统,它会警告/阻止你创建一个某些表中的新列可以“自然地”连接到您可能不希望它可以连接的其他表。

我想我的底线是,重视我的理智,希望我的应用程序有最大的正常运行时间,重视快速/干净的维护和升级等——在这种情况下,好的表设计意味着不使用自然连接(永远) .

于 2011-09-13T23:20:02.733 回答