Обновление партицированных таблиц в PostgreSQL?

Встала задача разбить большую табличку в PostgreSQL на партиции по датам. Таблички, индексы и ограничения создал и с INSERT'ом все ясно — вешаем триггер и выбираем партицию в зависимости от даты.


А как быть c триггером на UPDATE записи? В сети почему-то о нем умалчивают, может это я чего-то не того хочу. Вообще возможно ли такое и как? Киньте в меня примером или докой, пожалуйста.
  • Вопрос задан
  • 4333 просмотра
Решения вопроса 1
@galaxy
Нетипичная задача, обычно данные не таскают из партиции в партицию.
Тем не менее, ничего сложного нет. Делаете BEFORE UPDATE FOR EACH ROW триггер на дочерние таблицы. При апдейте на родительской таблице автоматически будет сделана попытка проапдейтить соответствующую строку дочерней и вызовется триггер. Триггерная функция должна проверить, должны ли данные остаться в текущей партиции (и в этом случае ничего не трогать) или, соответственно, удалить их из текущей и перенести в нужную. Короткий пример:
-- ключ нужен, чтобы точно идентифицировать строку таблицы
create table t(id int primary key);

-- партиции, без триггеров на INSERT
create table t1(primary key (id), check(id > 0 and id <= 10)) inherits(t);
create table t2(primary key (id), check(id > 10 and id <= 20)) inherits(t);

insert into t1 values (1), (4);
insert into t2 values (15);

test=# select * from t;
 id
----
  1
  4
 15

test=# select * from t1;
 id
----
  1
  4
 
test=# select * from t2;
 id
----
 15


create or replace function t_tg_proc() returns trigger as $$
begin
	raise notice 't_tg_proc called';
	if TG_TABLE_NAME = 't1' and NEW.id > 10 then
		delete from t1 where id = OLD.id; -- без primary key можно удалить лишнего
		insert into t2 values (NEW.*);
		return null; -- проигнорировать UPDATE
	end if;
	
	if TG_TABLE_NAME = 't2' and NEW.id <= 10 then
		delete from t2 where id = OLD.id;
		insert into t1 values (NEW.*);
		return null; -- проигнорировать UPDATE
	end if;
	
	return new; -- нормальный UPDATE
end $$ language plpgsql;

create trigger t1_tg before update on t1 for each row execute procedure t_tg_proc();
create trigger t2_tg before update on t2 for each row execute procedure t_tg_proc();

-- обычный UPDATE
update t set id = 5 where id = 4;
ЗАМЕЧАНИЕ:  t_tg_proc called
UPDATE 1

select * from t;
 id
----
  1
  5
 15
 
-- необычный UPDATE
update t set id = 11 where id = 1;
ЗАМЕЧАНИЕ:  t_tg_proc called
UPDATE 0

select * from t;
 id
----
  5
 15
 11
 
test=# select * from t1;
 id
----
  5
 
test=# select * from t2;
 id
----
 15
 11
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
alternativshik
@alternativshik
А какие трудности повесить триггер на апдейт? CREATE TRIGGER **** AFTER INSERT OR UPDATE OR DELETE ON ***
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы