PostgreSQL:影响多个表的约束

时间:2016-10-05 21:57:35

标签: sql postgresql constraints

我有一个实体的层次结构,每个实体可能有多个名称,因此我有一个单独的名称表。简化的SQL Schema如下所示:

CREATE TABLE users (
  id SERIAL NOT NULL PRIMARY KEY,
  -- some fields
);

CREATE TABLE entities (
  id SERIAL NOT NULL PRIMARY KEY,
  parent_id INTEGER NOT NULL,
  owner_id INTEGER NOT NULL,
  FOREIGN KEY (parent_id) REFERENCES entities(id),
  FOREIGN KEY (owner_id) REFERENCES users(id)
);

CREATE TABLE entity_names (
  id SERIAL NOT NULL PRIMARY KEY,
  entity_id INTEGER NOT NULL,
  name VARCHAR(30) NOT NULL,
  FOREIGN KEY (entity_id) REFERENCES entities(id)
);

我需要确保没有名称重复的实体(当然,具有相同的parent_idowner_id)。

我可以确保在使用以下查询向entity_names添加名称之前:

SELECT COUNT(t.id)
  FROM entity_names n
  JOIN entities e ON n.entity_id = e.id
  WHERE e.parent_id = 123 and e.owner_id = 456 and n.name = 'foo'

但是我想知道在数据库中实现这种约束是否可能(并且理智)?

2 个答案:

答案 0 :(得分:1)

Postgres中没有多重约束,但您可以通过将查询放在check的触发器中来模拟tag_names约束。

答案 1 :(得分:0)

entity_id表中的每个entity_names都标识entities表中的一行。尝试为特定实体添加重复名称如下所示:

INSERT INTO entity_names (entity_id, name) VALUES (2, 'Name1');

每个实体都拥有自己的父级和所有者,但仍然使用id进行唯一标识。因此,我认为你是在思考你的问题并且不需要跨表约束,而是一个简单的UNIQUE

CREATE UNIQUE INDEX ON entity_names (entity_id, name);

这假设没有两个记录与您的实体具有相同的parent_idowner_id - 我怀疑它是否有意义,因为对我来说它们看起来像候选键< /强>

如果事实并非如此(对我来说几乎不可信),那么创建一个返回触发器并在那里执行检查的函数,然后在BEFORE INSERT表上创建entity_names触发器。