sql - 为什么需要这个 UNIQUE 约束?

标签 sql postgresql

我正在尝试在 PostgreSQL 中设计架构,其中将包含两个相互交叉引用的表。然而,如果不添加冗余的UNIQUE约束(参见下面的代码),我会收到错误:错误:没有与引用表“节点”的给定键匹配的唯一约束

所以我的问题是:为什么需要这个额外的唯一约束以及有没有办法避免它的创建? (以减少运行时开销)。

CREATE TABLE objects (
  object_id serial NOT NULL PRIMARY KEY,
  root_node integer
);

CREATE TABLE nodes (
   node_id integer NOT NULL PRIMARY KEY,
   object_id integer REFERENCES objects
);

ALTER TABLE objects
  ADD CONSTRAINT root_node_fkey
  FOREIGN KEY (root_node) REFERENCES nodes(node_id);

-- Why this constaint is needed? Since node_id is primary key this combination should be already UNIQUE
ALTER TABLE nodes ADD CONSTRAINT node_id_object_id_unique UNIQUE (node_id, object_id);

ALTER TABLE objects
  ADD CONSTRAINT objects_nodes_fkey
  FOREIGN KEY (object_id, root_node)
  REFERENCES nodes (object_id, node_id);

最佳答案

https://www.postgresql.org/docs/current/static/ddl-constraints.html说:

5.3.5. Foreign Keys:

. . .

A foreign key must reference columns that either are a primary key or form a unique constraint. This means that the referenced columns always have an index (the one underlying the primary key or unique constraint); so checks on whether a referencing row has a match will be efficient.

https://mariadb.com/kb/en/sql-99/constraint_type-foreign-key-constraint/说:

A FOREIGN KEY Constraint is either a < Table Constraint> or a and defines a rule that constrains a foreign key to values that match only those values contained in a referenced unique key.


回复您的评论:

The idea is that each object will have collections of nodes associated with it and only one of nodes could be the root-node.

ALTER TABLE objects
  ADD COLUMN root_node_id integer,
  ADD CONSTRAINT objects_nodes_fkey
  FOREIGN KEY (root_node_id)
  REFERENCES nodes (node_id);

这样每个对象都引用一个节点。诚然,约束并不严格强制一个对象引用一个引用同一对象的节点。

如果您想要这种级别的强制执行,则必须创建您所要求的唯一约束(如果必须的话)。

关于sql - 为什么需要这个 UNIQUE 约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41194495/

相关文章:

postgresql - 同一列中的 Postgres 值分配

django - 长时间运行的 django 事务完整性错误

postgresql - 快速获取最后插入的 n 行

java - 使用带有 JDBC 的 MySQL 运行 .sql 脚本

sql - 按字母顺序连接字符串

mysql - 选择每个对话的最新消息

node.js - 格式错误的数组文字 : "1" error when updating column in postgres sequelize migration script

java - H2:如何判断表是否存在?

php - SQL Select 查询 where column like string with and without spaces

ruby-on-rails - 如何在雪豹上安装gem pg