Win*_*ker 5 postgresql partitioning postgresql-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');
Run Code Online (Sandbox Code Playgroud)
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
它不处理跨分区边界的更新。
因此你需要自己创建一个......这是你的一套:
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)
Run Code Online (Sandbox Code Playgroud)
这是规则和 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
Run Code Online (Sandbox Code Playgroud)
这是更新:
t=# update my_table set name = 'bbb' where name = 'abc';
INFO: : b
puf
-----
(1 row)
UPDATE 0
Run Code Online (Sandbox Code Playgroud)
检查结果:
t=# select tableoid::regclass,* from my_table;
tableoid | name
------------+------
my_table_b | bcd
my_table_b | bbb
(2 rows)
Run Code Online (Sandbox Code Playgroud)
再次:
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)
Run Code Online (Sandbox Code Playgroud)
当然,使用 json 来传递NEW记录看起来很难看。它确实很丑陋。但我没有时间研究PARTITION10 的新功能,所以不知道完成此任务的优雅方法。希望我能够给出如何解决问题的一般想法,并且您将生成更好整洁的代码。
更新
将此类规则限制ON update to my_table where left(NEW.name,1) <> left(OLD.name,1) do instead为释放繁重的操纵需求可能是个好主意
| 归档时间: |
|
| 查看次数: |
2040 次 |
| 最近记录: |