2016-10-05 3 views
0

У меня есть иерархическая структура сущностей, каждая из которых может иметь более одного имени, так что у меня есть отдельная таблица имен. Упрощенная схема SQL выглядит следующим образом:PostgreSQL: ограничение, которое влияет на несколько таблиц

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_id и owner_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' 

Но мне интересно, если это возможно (и вменяемый) осуществлять это ограничение в базе данных?

ответ

1

В Postgres нет многообразных ограничений, но вы можете эмулировать ограничение check, поставив запрос в триггер на tag_names.

0

Каждый entity_id в entity_names Таблица идентифицирует строку в пределах entities Таблица. При попытке добавить дубликат имя для конкретного объекта будет выглядеть следующим образом:

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

Каждый объект имеет собственный родитель и владелец, но до сих пор однозначно определены с id. Таким образом, я думаю, вы overthinking свой вопрос и не нуждаются в кросс-таблицу ограничений, но простой UNIQUE один:

CREATE UNIQUE INDEX ON entity_names (entity_id, name); 

Это при условии, что не существует двух записей с одинаковым parent_id и owner_id как ваши лица - Я сомневаюсь, что это имело бы какой-то смысл, поскольку для меня они кажутся нулевым ключом .


Если это на самом деле не так (вряд ли правдоподобно для меня), а затем создать функцию, которая возвращает триггер и выполнить проверку там, а затем создать BEFORE INSERT триггер на entity_names таблице.

Смежные вопросы