为什么不在SQL中添加一个JOINONE关键字来提示和强制每条记录最多只有一个匹配项?

15 浏览
0 Comments

为什么不在SQL中添加一个JOINONE关键字来提示和强制每条记录最多只有一个匹配项?

在编写SQL时,我经常遇到这个问题。我有两个表,它们应该是一对一关系,我希望在查询中能够轻松地确认这一事实。例如,简化的查询语句:

SELECT Person.ID, Person.Name, Location.Address1
FROM Person
LEFT JOIN Location ON Person.LocationID = Location.ID

当我阅读这个查询语句时,我想,如果Location表在其ID列上未强制执行唯一性,会怎么样?突然间,你的结果集中可能会出现相同的Person多次。当然,我可以去查看模式以确保它是唯一的,这样一切都会没问题,但为什么我不能简单地在查询中加上这个条件呢,如下所示:

SELECT Person.ID, Person.Name, Location.Address1
FROM Person
LEFT JOINONE Location ON Person.LocationID = Location.ID

一个类似这样的关键字(假设为"JOINONE")不仅可以让人类读取这个查询时100%清楚我们保证了每个Person记录都得到了一行,而且它可以让数据库引擎优化执行计划,因为它知道每次匹配不会超过一次,即使外键关系在模式中未定义。

这样做的另一个好处是数据库引擎可以强制执行它,所以如果数据实际上有多个匹配,就会抛出错误。这对于子查询已经发生了,例如:

SELECT Person.ID, Person.Name
 , (
    SELECT Location.Address1 
    FROM Location 
    WHERE Location.ID = Person.Location
   ) AS Address1
FROM Person

这很好,对人类读者来说非常明确,可以进行优化,并由数据库引擎强制执行。事实上,出于所有这些原因,我经常以这种方式处理问题。问题在于,除了分散注意力的语法之外,你只能用这种方式选择一个字段。(如果我还想选择城市、州和邮编呢?)如果你能够将这个表与其他所有JOIN一起流动,并在SELECT子句中选择任何字段,那将多好啊。

我在StackOverflow上找不到类似的问题,尽管我找到了很多类似的问题:人们想要选择一条记录。接近,但实际上是一种不同类型的目标,而且在我看来没有太多意义。

我发布这个问题是为了看看SQL语言中是否已经有我所不知道的机制,或者是否有人想出了一个有效的解决方法。一对一和一对多关系的概念对于关系数据库设计来说是如此基本,我对这种语言元素的缺失感到非常惊讶。

0
0 Comments

为什么在SQL中没有一个JOINONE关键字来提示和强制每个记录最多只有一个匹配?

这个问题的出现是因为SQL是两种语言的结合体。SQL中使用数据定义语言(DDL)来设置约束,包括唯一性约束。这是在数据操作语言(DML)之上的一层,SELECT语句所在的地方,我们知道在DDL中发出的语句可能会使DML中的语句失效。

查询无法阻止用户执行ALTER TABLE命令,从而在查询运行之间更改查询引用的字段的名称。

而且,查询很难针对不确定的约束进行防御性编写;如果需要,可以在数据库环境之外向某人索要信息来解决这个问题。这些信息也可以在环境内获得;在大多数引擎中,可以通过查询数据字典来获得。例如,在MySQL中,使用的是INFORMATION_SCHEMA。

正是因为DML和DDL之间的分离但交互的关系,我希望前者有这种机制。在查询中,我可以选择内连接而不是左连接,或者在模式中未定义的字段/规则上进行连接;那么为什么不能在查询的上下文中还能断言一个特殊的一对一关系呢?我可能根本没有对模式做出任何断言,只是对相关的数据集提出了一些要求。

0