postgres 水平分表,自動創建分區,按時間分表(轉)
關於觸發器函數的解釋:
重點說明:
- 觸發器函數自帶的很多參數,變量,可以直接調用
- 觸發器函數雖然沒有形參,但是也可以在觸發器中傳遞參數,參數可以在觸發器函數中通過變量:
TG_ARGV[0]
來獲取
CREATE TABLE public.tb_stranger_snap ( id serial8 NOT NULL, human_id varchar(50) NULL, thorough_count int4 NULL, device_snap_community_code varchar(30) NULL, snap_url varchar(200) NULL, update_time timestamp NULL DEFAULT now() ); CREATE INDEX tb_stranger_snap_device_snap_community_code_idx ON public.tb_stranger_snap (device_snap_community_code); --------觸發器---------------- CREATE OR REPLACE FUNCTION auto_insert_into_tb_stranger_snap() RETURNS trigger AS $BODY$ DECLARE time_column_name text ; -- 父表中用於分區的時間字段的名稱[必須首先初始化!!] curMM varchar(6); -- 'YYYYMM'字串,用做分區子表的后綴 isExist boolean; -- 分區子表,是否已存在 startTime text; endTime text; strSQL 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' ); select count(*) INTO isExist from pg_class where relname = (TG_RELNAME||'_'||curMM); -- 若不存在, 則插入前需 先創建子分區 IF ( isExist = false ) 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 := 'CREATE INDEX '||TG_RELNAME||'_'||curMM||'_INDEX_'||time_column_name||' ON ' ||TG_RELNAME||'_'||curMM||' ('||time_column_name||');' ; EXECUTE strSQL; END IF; -- 插入數據到子分區! strSQL := 'INSERT INTO '||TG_RELNAME||'_'||curMM||' SELECT $1.*' ; EXECUTE strSQL USING NEW; RETURN NULL; END $BODY$ LANGUAGE plpgsql; CREATE TRIGGER insert_tb_stranger_snap_trigger BEFORE INSERT ON tb_stranger_snap FOR EACH ROW EXECUTE PROCEDURE auto_insert_into_tb_stranger_snap('update_time');