来自
https://www.postgresql.org/docs/current/ddl-constraints.html
上关于外键约束的 PostgreSQL 文章:
假设您有产品表:
CREATE TABLE products ( product_no integer PRIMARY KEY, name text, price numeric );
我们还假设您有一个存储这些产品订单的表。 我们要确保订单表只包含订单 实际存在的产品。所以我们定义了一个外键约束 引用产品表的订单表:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products (product_no), quantity integer );
现在无法使用非 NULL product_no 条目创建订单 没有出现在产品表中。
这是0对多的关系吗?
如何设置一对多关系?
通过这样做?
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_no integer REFERENCES products (product_no) NOT NULL,
quantity integer
);
如果是这样,为什么 pgadmin4 在我按上面的方式配置表时会生成表示零对多的鱼尾纹符号?
鱼尾纹表示零对多关系。
不,它没有。不要将基数(方向性的)与关系类型混淆。圆圈表示
orders
基数的下限(并且可以省略) - 请参阅“多”与“零或多”/“一或多”crowfoot notation? on Software Engineering.
将
product_no
标记为NOT NULL
只会将零或一对多关系更改为恰好一对对多关系。两者通常被称为“一对多”或“1:N”关系。对于products
的基数,这将表示为破折号或破折号圆(或者,含糊地,只是破折号)。
现在乌鸦脚上的圆圈(或破折号)就在many边(
orders
) - 是…-to-零或-many还是…-to-one-or-many ?在您的模式中,它确实是一个零或多个基数,因为可以有任意数量的orders
-包括0
-对于product
.
请注意,实际的
0,1:1,N
、1:1..N
或 1..N:1..N
关系(不是 …:0,N
)出奇地难以在 SQL 中表示,因为您遇到了先有鸡还是先有蛋的问题,请参阅 如何创建真实关系-SQL Server 中的一对一关系 或 1:N 关系,其中 N 必须至少是一个条目)。
教程中的外键约束确保
product_no
中的值必须存在于表products
中。但是外键可以是NULL
,在这种情况下没有值,并且存在检查不适用(另见外键可以为NULL和/或重复)。
这就是为什么第一个关系是可选的一对多(有时被滥用地称为零对多)。在鱼尾纹中,这原则上会用空心圆(代表可选的 O)和三叉戟来表示。有时不指示关系的可选或强制性特征(即只有三叉戟)。
要将约束从可选更改为强制性,您确实只需将外键指定为
NOT NULL
,就像您在第二个选择中所做的那样。
我不是 pgadmin4 的专家,但快速浏览一下 图表工具文档 表明它只知道一对多和多对多关系,并且对话不允许有所作为介于可选和强制之间。例如,它是一个 known bug,它不能表示一对一的关系。
查看文档中的图表,在similar SO questions 和官方问题跟踪器中,图表工具似乎只知道:
和
这意味着该工具不能区分强制性(双杠代表一个,杠和三叉戟代表许多)和可选(圆形杠代表一个,圆形三叉戟代表许多),并且所使用的符号应理解为未指定对此。因此,小点不应被理解为可选的,而只是作为鱼尾纹三叉戟的奇特符号。
由于图表工具无法处理这些微妙之处,因此从 SQL 语句进行的逆向工程无法以准确的方式表示这些变化,即使它有算法可以在约束中检测到它们。