据我所知,许多DBMS(例如mysql,postgres,mssql)仅使用fk和pk组合来限制对数据的更改,但是它们很少用于自动选择要连接的列(就像自然连接使用名称一样)。这是为什么?如果您已经用pk / fk定义了2个表之间的关系,那么数据库为什么不能弄清楚如果我将那些表联接起来,我想在pk / fk列上联接它们?

编辑:稍微说明一下:

假设我有一个table1和table2。 table1在a列上有一个外键,该外键引用了table2在b列上的主键。现在,如果我加入这些表,则必须执行以下操作:

SELECT * FROM table1
JOIN table2 ON table1.a = table2.b


但是,我已经使用自己的键定义了table1.a对table2的引用。 b,因此在我看来,要使DBMS系统自动使用table1.a和table2.b作为联接列并不难,这样一来,您可以简单地使用:

SELECT * FROM table1
AUTO JOIN table2


但是,许多DBMS似乎并未实现这样的功能。

#1 楼

在许多情况下,连接两个表的方法不止一种。有关许多示例,请参见其他答案。当然,可以说在这些情况下使用“自动连接”将是一个错误。这样一来,只剩下少量可以使用的简单案例。

但是,这有一个严重的缺点!今天正确的查询,明天可能会变成错误,只需将第二个FK添加到同一表中即可。

再说一遍:通过添加列,不使用这些列的查询可能会变成“正确”变成“错误”!

这是一场维护噩梦,任何理智的风格指南都将禁止使用此功能。出于相同的原因,大多数已经禁止select *

如果可以提高性能,所有这些都可以接受。但是,事实并非如此。

总而言之,此功能只能在有限的一组简单情况下使用,不会提高性能,并且大多数样式指南仍会禁止使用它。

因此,大多数数据库供应商选择将时间花在更重要的事情上就不足为奇了。

评论


添加和更改列也可能会破坏NATURAL JOIN(这就是为什么我通常避免使用它们),但是我不认为dbms本身并不意味着不能实现基于外键的自动联接表的方式。

–周杰伦
16年8月1日在16:01

#2 楼

外键用于约束数据。即,强制执行参照完整性。而已。没什么。



您可以在同一张表上使用多个外键。请考虑以下情况,其中货物具有起点和终点。

table: USA_States
StateID
StateName

table: Shipment
ShipmentID
PickupStateID Foreign key
DeliveryStateID Foreign key


您可能希望根据取货状态加入。也许您想加入交货状态。也许您想同时执行两个联接! sql引擎无法知道您想要什么。

您经常会交叉联接标量值。尽管标量通常是中间计算的结果,但有时您会拥有一个特殊用途的表,该表具有1条记录。如果引擎尝试检测联接的前键...。这是没有意义的,因为交叉联接永远不会匹配列。
在某些特殊情况下,您将联接到两个都不唯一的列上。因此,这些列上不可能存在PK / FK。
您可能会认为上面的第2点和第3点无关紧要,因为您的问题是有关表之间何时存在单个PK / FK关系。但是,表之间存在单个PK / FK并不意味着您除了PK / FK之外不能再加入其他字段。 sql引擎不知道您想加入哪些字段。
说您有一个表“ USA_States”,以及另外5个表,这些表的FK指向各州。 “五个”表之间也有一些外键。 sql引擎应该自动将“五个”表与“ USA_States”联接吗?还是应该将“五个”相互联系?都?您可以设置这些关系,以便sql引擎进入一个无限循环,尝试将内容连接在一起。在这种情况下,sql引擎无法猜测您想要的内容。

总结:PK / FK与表联接无关。它们是独立的无关的事物。您经常加入PK / FK列只是自然而然的事情。

您想让sql引擎猜测它是完全,左,右还是内部联接吗?我不这么认为。尽管可以说,这比猜想要加入的列要轻些。

#3 楼


“可连接性”的概念。仅当具有相同名称的属性具有相同的类型时,关系r1r2才是可连接的...此
概念不仅适用于这样的联接,而且还适用于其他各种
操作[


SQL和关系理论:如何通过CJ Date编写准确的SQL代码

标准SQL已经具有这样的功能,众所周知就像NATURAL JOIN一样,并已在mySQL中实现。

尽管您的建议并不值得,但似乎是一个合理的建议。使用SQL Server(不支持NATURAL JOIN),我在Management Studio中使用SQL Prompt:在编写INNER JOIN时,它的InteliSense建议基于通用属性名称和外键同时使用ON子句,我发现它非常有用。但是,我非常希望看到一种新的(标准)SQL连接类型。

#4 楼

SQL首先出现!

紧随其后的是外键和外键约束,它们本质上是对“事务”样式应用程序的优化。

关系数据库最初被认为是一种应用方法使用关系代数在数学上可证明的方式对数据集进行复杂的查询。即对于给定的数据集和给定的查询,总是有一个正确的答案。

自那时以来,关系数据库已经走了很长一段路,而作为事务系统的持久层的主要用途并不是什么CODD等一切都可以设想。

但是,ANSI标准团体出于所有相互矛盾的目标和供应商的政策,一直努力保持SQL的“数学上可证明的”特性。

如果允许数据库从“隐藏的”外键数据中推断联接属性,则会丢失此属性(如果定义了一组以上的外键,请考虑清楚性)。

而且,读取SQL的程序员也不一定知道当前为这两个表定义了哪些外键,因此,需要检查数据库架构以弄清楚查询在做什么。

#5 楼

尽管定义了外键关系,但这并不意味着您要在所有查询中联接表。这是联接表的最可能方法,但是在某些情况下它是不正确的。


对于某些表,您可能希望使用两个表或其一部分的笛卡尔积目的。
可能还有其他字段可用于其他目的。
如果要连接三个或更多表,则其中一个表可能与两个或多个表相关。在这种情况下,通常只有一种可能的FK关系可能适合于查询。


#6 楼

您可能以错误的假设进行操作。您说“尽您所能”,但不提供任何经验或证据。如果pk或fk是查询的最佳索引,则将使用它。我不知道为什么会这样,但是我的猜测是查询的格式不正确。


现在编辑该问题已完全重写:您所描述的情况仅适用于一小部分查询。如果有12个表已联接怎么办?如果没有FK,该怎么办...。即使存在默认联接,我仍然总是出于可读性而指定联接。 (我不想查看数据,然后尝试找出要连接的内容)。

某些查询工具实际上为您执行了自动连接,然后允许您删除或编辑加入。我认为MS Access的查询生成器可以做到这一点。

最后,ANSII标准规定必须指定联接。这是足以不允许它的原因。

#7 楼

数据库无法安全地执行此操作的原因很多,其中包括添加/删除外键将改变预写查询的含义,包括应用程序源代码中的查询。大多数数据库也没有很好的外键集,无法涵盖您可能想要执行的所有可能的联接。同样出于更好或价值的考虑,外键通常会被删除以加快系统运行速度,并且不能在从文件中以“错误”顺序加载的表上使用。

但是没有理由查询设计工具或文本编辑器无法在外键的帮助下自动完成联接,就像它们为您提供列名的智能感知一样。如果工具出错,则可以编辑查询并保存完整定义的查询。这样的工具还可以有用地利用按“父”表名称和在父/子表中具有相同名称的列来命名外键列的约定。

#8 楼

自然连接“自动”在公共列相等的情况下进行连接,但是只有在基于表含义和所需结果的基础上,才应编写自然连接。没有“自动”知道如何“连接”两个表或以任何其他方式“查询”出现在查询中的任何表。我们不需要知道要查询的约束。它们的存在只是意味着输入可能会受到限制,因此输出可能也会受到限制。您可以定义某种join_on_fk_to_pk运算符,该运算符根据声明的约束自动“连接”;但是,如果您希望查询的含义保持不变(如果仅更改约束,而不更改表的含义),则必须更改该查询以不使用新的声明的内容。尽管有任何约束更改,仅使用join&条件给出的查询就已经具有相同的含义。

约束的内容(包括PK,FK,UNIQUE和CHECK)不影响表的含义。当然,如果表的含义发生变化,则矛盾可能会发生变化。但是,如果约束条件发生变化,并不意味着查询也应该发生变化。

人们不需要知道约束条件即可查询。了解约束意味着我们可以使用更多的表达式,这些表达式如果没有约束保持就不会返回相同的答案。例如,通过UNIQUE期望一张表有一行,因此我们可以将其用作标量。如果假定但未声明约束,则这些查询可能会中断。但是,声明一个未假定查询的约束无法打破它。

是否有任何经验法则可以从易于理解的描述中构造SQL查询?

#9 楼

原因是存在语言,然后是基础主体。该语言是稀疏的,缺少许多您希望在通用语言中看到的功能。这恰好是一个不错的功能,尚未添加到语言中,可能不会添加。这不是一门枯燥的语言,所以有希望,但我不会乐观。

正如其他人指出的那样,某些实现使用扩展,其中join(列)基于同一列联接两个表名称,有点相似。但是它并没有广泛传播。请注意,此扩展名与SELECT * FROM employee NATURAL JOIN department;语法不同,后者没有包括指定使用哪些列的方法。两者都不依赖于表之间的关系,这使它们不可靠(自然连接语法比扩展更重要)。

“ PKFK上的内部连接表”没有根本的障碍,其中PKFK是关键字的含义在“两个表之间定义的外键关系”中,同一个表可能存在多个fk的问题,但这可能只会导致错误。问题是设计语言的人是否认为a)一个好主意和b)比其他一些语言更改更好地进行工作...

#10 楼

如果假设忽略ON子句是基于参照完整性遵循字段,那么您将如何做笛卡尔乘积?

编辑:使用AUTO
这样做的优点是键入量少一些您不必知道它们是如何联接的,也不必记住复杂的联接。如果关系芯片发生更改,它将被自动处理,但是除了早期开发,这种情况很少发生。

现在要做的就是确定在关系更改期间是否所有AUTO联接都成立,以匹配select语句的意图。

#11 楼


为什么数据库无法弄清楚如果我将那些表联接到pk / fk列上呢?


部分原因是:
/>
1-理论上,您可以将两个表中任意列上的表连接起来。尽管这不是普遍做法,但它是有效的。请记住,SQL就像一种编程语言,它不了解课程和名称列中包含的信息,对于SQL而言,在这方面没有多大意义。

2-联接的类型不同(左联接,右联接,内联接)-内联接仅是其中的一种。

3-SQL标准可以遵循该原则一种较低级的语言,它允许较高级的方言使用它来形成智能。如果您想到的是第四代语言与第三代语言,则比较起来会更加清晰。实际上,我使用的一种工具IEF允许您编写如下代码:

ReadEach Customer 
Where Customer Places Orders and That Customer LivesIn "California" 
and OrderValue > 100.00


总而言之,您的建议很有趣,可以作为以下建议的一部分来实施标准或作为存储过程(默认为内部联接)。