是时候告别 SQL 中的 Null 和 Bags 了

Time to Move On: Querying Without Nulls and Bags

是时候告别 SQL 中的 Null 和 Bags 了

SQL 凭借其声明式特性成为数据库领域的成功典范,但随着问题复杂度的提升,早期设计中的妥协已显弊端。作者基于 Rel 语言的开发经验指出,完全规范化的关系模型不仅能避免 Codd 所称的“损坏关系”和常见的 Bags(多重集),更能彻底消除被称为“十亿美元错误”的 Null 值。文章论证了 Null 和 Bags 并非不可避免的恶,其存在理由经不起推敲。通过摒弃这些概念,采用无 Null 且基于集合语义的语言,我们将迎来更清晰、更强大的查询能力。

在 SQL 世界中,Bags 和 Null 被视为不可避免的恶,但我们认为这种恶完全是可以避免的:为它们辩护的理由在仔细审视下便会烟消云散。
  1. mamcx

    这篇文章确实有一些亮点,但在我看来,它有两个主要问题,这在我们团队构建 RDBMS 时观察到了:

    * 它再次忽略了处理 null 的最佳方案:代数类型(Algebraic types)。一旦你拥有了这个,很多问题就迎刃而解了。

    * 关于反对 Bags(多重集/允许重复的集合)的论点:

    这篇文章最好的观点是,RDBMS 内部实际上使用了不同的数据结构和时间表示,这些对用户来说是不需要关心的。这点没错。

    然而,它紧接着就得出了 Bags 不应该向用户展示的结论,尽管文章也承认需要展示它们。

    这是错误的,而且一个经常被忽视的主要原因是:它假设两个相同的值不应该同时存在。

    我完全可以有 "Jhon, Jhon",代表两个不同的人,此时我尚不知道如何区分他们,添加一个 Id 也帮不了我,但这组数据本身就是正确的。

    语言必须允许我处理这种情况。声称数组语言、过程式、函数式、命令式、声明式等语言可以处理,而关系型语言却不行,这简直荒谬。

    文章说这种限制是为了语言的纯粹性,这倒是真的,在某些情况下这很理想,但这种纯粹性应该是引擎/编译器去跟踪的,而不是为了这个扭曲我的数据。

    至于关于 Bags 性能被轻视的部分,很容易通过实现一个 DBMS 并进行性能分析(profile)来驳斥。

    P.D:确实,Set(集合)能解锁很多优势,在某些情况下是理想的。但一旦你进入现实世界,很快就会看到你需要两者兼备,就像仅靠 B 树是不够的,然后还有基于哈希的索引……

  2. bbkane

    这不公平,但读完摘要后我的第一反应是“哦,太好了,又来了一个”。

    已经有好几种语言声称要修复 SQL,但据我所知(我很想看到反例),它们都没有获得足够广泛的采用,以至于能被称为真正的继任者。

    我能想到的原因有:

    - SQL 已经深耕了 50 年——所有 RDBMS 都支持它!大多数监控系统也支持它!任何继任语言都需要一个良好的互操作性故事,以便人们能将其与现有系统配合使用。

    - SQL 对于日常的普通任务来说已经够好了——而且现在,当我迷失在递归查询或窗口函数中时,我可以向 LLM 寻求帮助。也许继任语言可以在 IDE 支持或其他开发/代理体验方面胜出。

    继任语言往往只替换 SQL 的部分功能(通常是查询部分,而不是插入/更新部分)。我认为 PRQL 就是这样做的(再次强调,我很想被打脸)。现在开发者得学两种语言了?

    我的观点是,一种继任语言不能仅仅修复 SQL 的语义问题,要取得成功,它还必须在生态系统(甚至政治层面)上提供巨大的提升。我在摘要中没有看到任何这些内容,这让我热情全无。

  3. reaanb2

    我们能否也停止把行(rows)当作概念模型图中的顶点(vertices)来谈论,转而开始将它们视为 n 元关联(n-ary associations)或事实(facts)?

同日更多故事

2026-08-13