Postgres 10: строки автоматически перемещаются между разделами?
Предполагая, что у меня есть родительская таблица с дочерними разделами, которые создаются на основе значения поля.
Если значение этого поля изменяется, есть ли способ заставить Postgres автоматически перемещать строку в соответствующий раздел?
Например:
create table my_table(name text)
partition by list (left(name, 1));
create table my_table_a
partition of my_table
for values in ('a');
create table my_table_b
partition of my_table
for values in ('b');
В этом случае, если я изменю значение name
в ряд от aaa
в bbb
Как я могу заставить его автоматически переместить этот ряд в my_table_b
,
Когда я пытался это сделать, (т.е. update my_table set name = 'bbb' where name = 'aaa';
), Я получаю следующую ошибку:
ERROR: new row for relation "my_table_a" violates partition constraint
1 ответ
он не обрабатывает обновления, которые пересекают границы раздела.
таким образом, вам нужно создать его самостоятельно... вот ваш набор:
t=# insert into my_table select 'abc';
INSERT 0 1
t=# insert into my_table select 'bcd';
INSERT 0 1
t=# select tableoid::regclass,* from my_table;
tableoid | name
------------+------
my_table_a | abc
my_table_b | bcd
(2 rows)
вот правило и fn():
t=# create or replace function puf(_j json,_o text) returns void as $$
begin
raise info '%',': '||left(_j->>'name',1);
execute format('insert into %I select * from json_populate_record(null::my_table, %L)','my_table_'||left(_j->>'name',1), _j);
execute format('delete from %I where name = %L','my_table_'||left(_o,1), _o);
end;
$$language plpgsql;
CREATE FUNCTION
t=# create rule psr AS ON update to my_table do instead select puf(row_to_json(n),OLD.name) from (select NEW.*) n;
CREATE RULE
вот обновление:
t=# update my_table set name = 'bbb' where name = 'abc';
INFO: : b
puf
-----
(1 row)
UPDATE 0
результат проверки:
t=# select tableoid::regclass,* from my_table;
tableoid | name
------------+------
my_table_b | bcd
my_table_b | bbb
(2 rows)
снова:
t=# update my_table set name = 'a1' where name = 'bcd';
INFO: : a
puf
-----
(1 row)
UPDATE 0
t=# select tableoid::regclass,* from my_table;
tableoid | name
------------+------
my_table_a | a1
my_table_b | bbb
(2 rows)
Конечно, используя JSON для передачи NEW
запись выглядит некрасиво. И это действительно ужасно. Но я не успел изучить новый PARTITION
особенность 10, поэтому не знаю элегантного способа сделать это задание. Надеюсь, я мог бы дать общее представление о том, как вы можете решить проблему, и вы получите лучший аккуратный код.
Обновить
его, вероятно, хорошая идея ограничить такое правило ON update to my_table where left(NEW.name,1) <> left(OLD.name,1) do instead
, чтобы освободить тяжелые манипуляции нужно