2016-12-12 1 views
1

Я хочу иметь возможность выполнять некоторую логику для внешних ключей. Удерживать DELETE. В зависимости от логики, я либо захочу CASCADE, либо RESTRICT.Условная логика для ссылки ON DELETE для внешнего ключа

Мои столы:

CREATE TABLE users (
    user_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY 
); 

CREATE TABLE teams (
    team_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY 
); 

CREATE TABLE documents (
    document_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY 
    user_id uuid REFERENCES users ON DELETE /*do logic here*/, 
    team_id uuid REFERENCES teams ON DELETE /*do logic here*/, 
    content text 
); 

В моей (очень простой) Таблицы document могут принадлежать user и/или team.

Что касается documents, если кто-то удаляет пользователя документа и документа team_id IS NULL, то каскадное удаление в документе (или наоборот, с user_id и team_id).

В противном случае, если кто-то удалит пользователя документа, а team_id документа НЕ НЕТ, то ОГРАНИЧИВАЙТЕ удаление пользователя (или наоборот с user_id и team_id).

Я не видел никакого способа выполнить это в документации. Нужно ли мне делать эту логику в моем серверном коде, а не в базе данных? Мне нужны дополнительные уровни целостности данных.

ответ

2

вполне возможно, но не напрямую. Вам нужен триггер. Сначала установите внешний ключ, чтобы быть RESTRICT

CREATE TABLE documents (
    document_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY, 
    user_id uuid REFERENCES users ON DELETE RESTRICT, 
    team_id uuid REFERENCES teams ON DELETE RESTRICT, 
    content text 
); 

Затем создайте функцию триггера и триггер для таблицы пользователя

CREATE OR REPLACE FUNCTION user_delete() 
RETURNS TRIGGER AS $$ 
BEGIN 
    DELETE FROM documents WHERE team_id IS NULL and user_id = OLD.user_id; 
    RETURN OLD; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER user_delete_trigger BEFORE DELETE ON users FOR EACH ROW  EXECUTE PROCEDURE user_delete(); 

Затем сделать то же самое для таблицы команды.

CREATE OR REPLACE FUNCTION team_delete() 
RETURNS TRIGGER AS $$ 
BEGIN 
    DELETE FROM documents WHERE user_id IS NULL and team_id = OLD.team_id; 
    RETURN OLD; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER team_delete_trigger BEFORE DELETE ON users FOR EACH ROW  EXECUTE PROCEDURE team_delete(); 

и это, я считаю, делает именно то, что вы ищете.