CREATEORREPLACEFUNCTIONpublic.auto_insert_before_table()RETURNStriggerLANGUAGE plpgsql
AS $function$
DECLARE
time_column_name text;-- 父表中用于分区的时间字段的名称[必须首先初始化!!]
curMM varchar(6);-- 'YYYYMM'字串,用做分区子表的后缀
isExist boolean;-- 分区子表,是否已存在
startTime text;
endTime text;
strSQL text;
partitionTableName text;-- 分区表的完整名称BEGIN-- 调用前,必须首先初始化(时间字段名):time_column_name [直接从调用参数中获取!!]
time_column_name := TG_ARGV[0];-- 判断对应分区表 是否已经存在?EXECUTE'SELECT $1.'||time_column_name INTO strSQL USING NEW;
curMM := to_char( strSQL::timestamp,'YYYYMM');-- 构建分区表的名称
partitionTableName := TG_RELNAME ||'_'|| curMM;-- 检查分区表是否已存在 SELECTEXISTS(SELECT1FROM pg_class WHERE relname = partitionTableName)INTO isExist;-- 若不存在, 则插入前需 先创建子分区IFnot isExist THEN-- 创建子分区表
startTime := curMM||'01 00:00:00.000';
endTime := to_char( startTime::timestamp+interval'1 month','YYYY-MM-DD HH24:MI:SS.MS');
strSQL :='CREATE TABLE IF NOT EXISTS '||TG_RELNAME||'_'||curMM||' ( CHECK('||time_column_name||'>='''|| startTime ||''' AND '||time_column_name||'< '''|| endTime ||''' )
) INHERITS ('||TG_RELNAME||') ;';EXECUTE strSQL;-- 设置主键索引,
strSQL :=format('ALTER TABLE %I ADD PRIMARY KEY (%I);',
partitionTableName,'id');EXECUTE strSQL;ENDIF;-- 插入数据到子分区! ON CONFLICT (id) DO NOTHING 当遇到id重复时,不插入
strSQL :='INSERT INTO '||TG_RELNAME||'_'||curMM||' SELECT $1.* ON CONFLICT (id) DO NOTHING';EXECUTE strSQL USING NEW;RETURNnull;-- new 返回受影响的行数;此处返回NULL, 触发这个触发器的INSERT/UPDATE/DELETE命令不会被执行。如果行级的BEFORE触发器返回非空的值,则INSERT/UPDATE/DELETE命令继续执行END
$function$
创建一个触发器,绑定上述函数
-- time是传参用的,用于函数里面的time_column_nameCREATETRIGGER insert_table_trigger
BEFORE INSERTON`table`FOR EACH ROWEXECUTEPROCEDURE auto_insert_before_table('time');