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

Vla*_*hev 9 sql orm variant relational-database algebraic-data-types

假设您正在OCaml/F#/ SML/Haskell中编写应用程序,并希望将数据保存在关系数据库中.将产品类型(记录和元组)映射到关系很容易,但是如何将变体类型映射到关系?

具体来说,如何在关系数据库中保留类似下面的类型?

(* OCaml *)
type t = 
  | Foo
  | Bar of string
  | Baz of int * int * int
Run Code Online (Sandbox Code Playgroud)

sol*_*ack 7

这看起来很乏味,但我会为总和中的每个产品创建一个表格。

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);
Run Code Online (Sandbox Code Playgroud)

您可能希望存储一些元数据以及每种类型的记录:

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

这暗示了一个外键约束:

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);
Run Code Online (Sandbox Code Playgroud)

如果您更严格,您可以想象存储ty带有类型名称的列并使用它来构造复合外键。(如LedgerSMB 博客中“不应该使用表继承的地方”所述。)