Напишете тригерна функция. Нещо подобно:
CREATE OR REPLACE FUNCTION trg_backup_row()
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO other_tbl
SELECT (OLD).*, t.other_col -- all columns of from old table
-- SELECT OLD.col1, OLD.col2, t.other_col -- alternative: some cols from old tbl
FROM third_tbl t
WHERE t.col = OLD.col -- link to third table with info from deleted row
AND <unique_condition_to_avoid_multiple_rows_if_needed>;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
И тригер ON DELETE
. Като това:
CREATE TRIGGER delaft
AFTER DELETE
ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_backup_row();
Ключови елементи
-
Най-добре го направете тригер
СЛЕД ИЗТРИВАНЕ
иЗА ВСЕКИ РЕД
. -
За да върнете всички колони от старата таблица, използвайте синтаксиса
(OLD).*
. Вижте ръководството за достъп до съставни типове . Като алтернативаOLD.*
също е валиден синтаксис, защотоOLD
се добавя къмFROM
клауза имплицитно. ЗаVALUES
израз, той трябва да бъде(OLD).*
, обаче. Като:INSERT INTO other_tbl VALUES((OLD).*, some_variable)
-
Можете да включите стойности от всяка друга таблица, както демонстрирам. Просто се уверете, че получавате един ред или създавате множество записи.
-
Тъй като тригерът задейства
СЛЕД
събитието, функцията може даВРЪЩА NULL
.
Относно видимостта
В отговор на внимателния коментар на @couling.
Докато външните ключове могат да бъдат декларирани като ОТЛОЖЕНИкод>
, това ще отложи само проверката на целостта, но не и самото изтриване. Редове, които са изтрити в тригери, изпълнени преди текущия или от ON DELETE CASCADE
външните ключове повече няма да се виждат по време на това СЛЕД ИЗТРИВАНЕ
се извиква тригер. (Очевидно всичко се случва в една транзакция. Нито една от тези подробности няма значение за други транзакции, които ще видят всички или нито един от ефектите. Обърнете се към ръководството за повече относно MVCC модел и изолация на транзакция
.)
Следователно, ако искате да включите стойности от редове, зависещи по такъв начин във вашия INSERT
, не забравяйте да извикате този тригер преди тези редове се изтриват.
Може да се наложи да направите този тригер ПРЕДИ ИЗТРИВАНЕ
.
Или може да означава, че трябва да подредите тригерите си по съответния начин, ПРЕДИ
тригерите идват преди СЛЕД
задейства, очевидно. И тригерите на същото ниво се изпълняват в азбучен ред
.
Въпреки това, докато съм супер точен тук, мога също да добавя, че промените, направени в реда (или в зависимост от редовете) в други ПРЕДИ
тригерите също се виждат само ако са извикани before този.
Моят съвет е да го направите СЛЕД
задействането беше, защото е по-малко податливо на усложнения и по-евтино, ако друго задействане може да отмени (върни) DELETE
по средата на операцията - стига нито едно от горните да не е приложимо.