使用关系型数据库建模代数数据类型

12

假设你正在使用OCaml/F#/SML/Haskell编写应用程序,并想要将数据持久化到关系数据库中。将产品类型(记录和元组)映射到关系很容易,但如何将变量类型映射到关系呢?

具体来说,如果有以下类型,你该如何在关系数据库中进行持久化?

(* OCaml *)
type t = 
  | Foo
  | Bar of string
  | Baz of int * int * int

你可以给一个实际数据存储的例子吗? - Shnugo
我的第一个想法是使用XML。您可以将任何类型的分层结构数据与描述性元数据(属性)存储在一起。但是您需要高逻辑来解释此内容... - Shnugo
@shnugo,正如我所提到的,我对关系型数据库很感兴趣。 - Vladimir Keleshev
你好,你没有说明想使用哪种 RDBMS。我正在使用 SQL Server。在关系型数据库模式 内部 使用 XML 有不可思议的可能性。只需将 XML 列定义为表的一部分,并在其中放置任何数据即可。这样做,您可以将 RDBMS 的强大功能与 XML 的灵活性相结合。这只是一个想法... - Shnugo
https://blog.typeable.io/posts/2019-11-21-sql-sum-types.html - YisraelU
1个回答

10

看起来很繁琐,但我会为每个产品创建一个总计表。

CREATE TABLE foo (id uuid PRIMARY KEY);

CREATE TABLE bar (id uuid PRIMARY KEY,
                  s  text NOT NULL);

CREATE TABLE baz (id uuid PRIMARY KEY,
                  a  integer NOT NULL,
                  b  integer NOT NULL,
                  c  integer NOT NULL);

您可能想要在每种类型的记录中存储一些元数据:

CREATE TABLE envelope (id uuid PRIMARY KEY,
                       t  timestamptz NOT NULL DEFAULT now(),
                       by text NOT NULL DEFAULT sessions_user);

这意味着有一个外键约束:

CREATE TABLE foo (id uuid PRIMARY KEY REFERENCES envelope);

CREATE TABLE bar (id uuid PRIMARY KEY REFERENCES envelope,
                  s  text NOT NULL);

CREATE TABLE baz (id uuid PRIMARY KEY REFERENCES envelope,
                  a  integer NOT NULL,
                  b  integer NOT NULL,
                  c  integer NOT NULL);

如果您更加严格,可以考虑存储一个名为ty的列,并使用它来构建一个复合外键。(如LedgerSMB博客中所述的“不要使用表继承的地方”。)


我最近更多地思考了这个问题,并设计了一个包含中间表的方案,用作外键目标。可以在此处找到一些示例代码:https://github.com/solidsnack/pg-sql-variants - solidsnack
我该如何存储对t的引用? - nafg
存储一个信封的引用。 - solidsnack
有什么被编辑过吗?我自己的问题都看不懂了 ;) - nafg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接