postgres 自动水平分表,简单示例

创建父表:

create table test_id
(
    id integer
);

创建触发器函数:

说明:触发器每隔1000笔数据会插入一个新表中,当然id 需要是连续不重复的情况.

drop function if exists func_trigger_insert_test_id;
create or replace function func_trigger_insert_test_id()
    returns trigger as
$$
declare
    var_id         integer;
    var_is_exist   boolean;
    var_table_name varchar(33);
    var_sql_create text;
    var_sql_insert text;
begin
    --     获取当前需要使用的表名:
    var_table_name = 'test_id' || trunc(new.id, -3):: varchar(33);
    var_id = trunc(new.id, -3);
    select count(1) into var_is_exist from pg_class where relname = var_table_name;
    if (var_is_exist = false) then
--         创建新的表格.
        var_sql_create := format('    create table if not exists %s
    (
         check ( id >= %s and id <= %s )
    ) inherits (test_id);', var_table_name, var_id, var_id + 999);
        raise notice 'var_id:%',var_id;
        execute var_sql_create;
    end if;
    var_sql_insert = format('insert into %I select $1.*;', var_table_name);
    execute var_sql_insert using new;

    --     表格创建完成后插入数据:
--     raise notice 'TG_RELNAME:%',tg_relname;
    raise notice 'new:%',new.id;

    return null;
end
$$
    language plpgsql
    volatile;

创建触发器:

create trigger trigger_insert_test_id
    before insert
    on test_id
    for each row
execute procedure func_trigger_insert_test_id();

插入数据测试:

insert into test_id
select generate_series(1, 5000);

测试效果:


update 二〇二〇年〇九月十五日:
今天重新看触发函数看不懂了!(⊙﹏⊙)b
$1代表新增的那笔记录
using new是什么意思: 结合$1使用的相当与位置参数值。

关于execute $ using 用这个函数解释下会比较清楚:

create or replace function func_test()
    returns timestamp
as
$$
declare
    var_test varchar(33) default 'tb';
    var_date timestamp;
begin
    var_test:='tb';
    execute 'select $1' into var_date using now();
    return var_date;
end
$$
    language plpgsql volatile;

不过变量不能用于表名和字段上。要使用还是使用%I吧。

原文地址:https://www.cnblogs.com/qianxunman/p/13352619.html