#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть две таблицы:
CREATE TABLE Registered(student TEXT, course CHAR(6))
CREATE TABLE WaitingList(student TEXT, course CHAR(6), position INT)
(студент, курс) являются парами первичных ключей в обеих таблицах, и как студент, так и курс являются индивидуально внешними ключами, на которые ссылаются из других таблиц.
У меня также есть представление
CREATE VIEW Registrations(student, course, status)
Которое представляет собой объединение двух таблиц со статусом либо ожидающий, либо зарегистрированный в зависимости от того, из какой таблицы происходит пара (студент, курс).
Затем я создаю триггер и функцию:
CREATE FUNCTION unregistration_function() RETURNS TRIGGER AS $
BEGIN
IF (EXISTS(SELECT * FROM WaitingList WHERE student = OLD.student AND course = OLD.course)) THEN
--delete OLD.student from WaitingList and then update WaitingList position;
ELSIF (EXISTS(SELECT * FROM Registered WHERE student = OLD.student AND course = OLD.course)) THEN
--delete OLD.student from Registered;
ELSE
RAISE EXCEPTION 'Student % is not registered or on waitinglist for course %', OLD.student, OLD.course;
END IF;
RETURN OLD;
END;
$ LANGUAGE plpgsql;
CREATE TRIGGER unregistration
INSTEAD OF DELETE FROM Registrations
FOR EACH ROW
EXECUTE PROCEDURE unregistration_function();
Функция триггера работает, так как в ней успешно отменяется регистрация студентов на курсах или они удаляются из списка ожидания. Однако, в случае, когда студент не зарегистрирован на курсе и не находится в списке ожидания для курса, он не вызывает исключения, но все равно сообщает об успешной отмене регистрации, даже если ничего не было незарегистрировано.
Я не уверен, чего мне не хватает, так как условие WHERE должно возвращать false в предложениях IF и ELSIF в этом случае, и исключение должно быть вызвано. Насколько я понимаю из документации, создание ИСКЛЮЧЕНИЯ должно прервать текущую транзакцию?
Просто ли из-за того, что это оператор УДАЛЕНИЯ, прерывание транзакции приводит к тому, что DELETE просто завершается с 0 удаленными строками, которые по-прежнему считаются «успешными» и, следовательно, не отображают мое сообщение об ошибке?
Комментарии:
1. Попробуйте
IS NOT DISTINCT FROM
вместо=
этого для сравнения.
Ответ №1:
Вызывается DELETE
для каждой строки, которая будет удалена.
Если вы выполните:
delete from registrations
where student = XXX;
и student
отсутствует в таблице или представлении, тогда триггер не вызывается.
Вам нужно посмотреть на количество удаленных строк, чтобы увидеть, было ли что-нибудь удалено.
Комментарии:
1. Конечно … так просто, и все же я пропустил это, спасибо.
2. @KnutKnutsson . , , я признаю, что потребовалось некоторое размышление, чтобы понять, что это проблема. Это тонкий момент (хотя и очевидный, когда вы его видите).