Как изменить SQL Server вместо триггера удаления на PostgreSQL - PullRequest
0 голосов
/ 29 июня 2019

Я хотел бы сделать тот же тип триггера в PostgreSQL, что и в SQL Server.

Я пытался изменить код на функцию, и у меня было много ошибок, не указывающих, что не так, но каким-то образом мне удалось изменить свой кодчто он может работать, но затем, вызывая триггер, я получаю сообщение об ошибке:

старая связь не существует

Триггер SQL Server:

CREATE TRIGGER DeleteUser 
ON users
INSTEAD OF DELETE
AS
BEGIN
    IF EXISTS (SELECT * 
               FROM deleted d
               LEFT JOIN orders as o on o.user_id = d.id
               WHERE o.id IS NOT NULL)
    BEGIN
        ROLLBACK
        RAISERROR('Cannot delete this record: user already ordered something',16,1)
    END
    ELSE
    BEGIN
        DELETE FROM users
        WHERE EXISTS (SELECT * FROM deleted d WHERE d.id = users.id)

        PRINT('Deleted!')
    END
END
GO

Адаптированный код для Postgres:

Функция:

CREATE FUNCTION delete_user()
RETURNS TRIGGER
AS $$
BEGIN
IF EXISTS (
    SELECT * 
    FROM old d
    LEFT JOIN orders as o on o.user_id = d.id
    where o.id is not null
    ) THEN
    RAISE EXCEPTION 'Cannot delete this record: user already ordered something';
ELSE
      DELETE FROM users
      WHERE EXISTS (Select * from deleted d where d.id = users.id);
      RAISE NOTICE 'Deleted!';
END IF;
END;
$$
LANGUAGE plpgsql;

Триггер:

CREATE TRIGGER deletion_of_user
    BEFORE DELETE
    ON public.users
    FOR EACH ROW
    EXECUTE PROCEDURE public.delete_user();

1 Ответ

2 голосов
/ 29 июня 2019

Вам не нужно удалять в коде триггера.Так как это триггер before, достаточно просто вернуть запись old, чтобы удаление произошло.

Вы создали триггер уровня строки (то, чего нет у SQL Server), поэтому запись old - это всего лишь одна строка, которую нельзя выбрать из нее.Просто используйте его в предложении WHERE оператора SELECT.

CREATE FUNCTION delete_user()
RETURNS TRIGGER
AS $$
BEGIN
IF EXISTS (
    SELECT * 
    FROM orders as o 
    where o.user_id = old.id; --<< no need for a join
    ) THEN
    RAISE EXCEPTION 'Cannot delete this record: user already ordered something';
ELSE
    RAISE NOTICE 'Deleted!';
    return old; --<< tell Postgres to continue with the delete
END IF;
END;
$$
LANGUAGE plpgsql;

Но (неправильно) использование триггера для этого является неправильным подходом (как в Postgres, так и в SQL Server).Вы должны объявить внешний ключ из таблицы заказов, ссылающейся на таблицу пользователей, что также предотвратит удаление - и, возможно, намного эффективнее.

...