PostgreSQL函数中基于reg_dt最大日期删除表分区的实现咨询
基于reg_dt最大日期删除PostgreSQL分区的函数修正
你原函数中的删除分区语句存在语法错误,同时硬编码表名的设计也会限制函数通用性,以下是修正后的完整函数及关键说明:
CREATE OR REPLACE FUNCTION cbsadm.create_part_tbl_cpvmm(cpvmm_custi_m text) RETURNS void LANGUAGE plpgsql AS $function$ DECLARE v_max_reg_dt date; v_drop_part_name text; BEGIN -- 终止持有目标表锁的后端进程(使用函数参数替换硬编码表名) PERFORM pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid IN ( SELECT pid FROM pg_catalog.pg_locks pl WHERE pl.relation IN ( SELECT oid FROM pg_catalog.pg_class pc WHERE pc.relname = cpvmm_custi_m AND pc.relowner IN ( SELECT usesysid FROM pg_catalog.pg_user WHERE usename = 'cbsadm' ) ) ); -- 创建明日的分区 EXECUTE 'CREATE TABLE ' || quote_ident(cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD')) || ' PARTITION OF ' || quote_ident(cpvmm_custi_m) || ' FOR VALUES FROM (''' || to_char(now() + interval '1 day','YYYYMMDD') ||''') TO (''' || to_char(now() + interval '2 day','YYYYMMDD') || ''') TABLESPACE tbs_cbs;'; -- 添加唯一约束 EXECUTE 'ALTER TABLE '|| quote_ident(cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD')) || ' ADD CONSTRAINT ' || quote_ident(cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD') || '_un') || ' UNIQUE (reg_dt, card_no, card_sttl_acno);'; -- 创建唯一索引 EXECUTE 'CREATE UNIQUE INDEX ' || quote_ident('ix_'|| cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD')) || ' ON ' || quote_ident(cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD')) || ' (reg_dt, reg_seqno, cstno) TABLESPACE tbs_cbs;'; -- 分析新分区 EXECUTE 'ANALYZE '|| quote_ident(cpvmm_custi_m || '_' || to_char(now() + interval '1 day','YYYYMMDD')) ||';'; -- 获取主表reg_dt的最大日期 EXECUTE 'SELECT max(reg_dt) FROM ' || quote_ident(cpvmm_custi_m) INTO v_max_reg_dt; -- 计算要删除的分区日期(最大日期减10天)并生成分区名 IF v_max_reg_dt IS NOT NULL THEN v_drop_part_name := cpvmm_custi_m || '_' || to_char(v_max_reg_dt - interval '10 days', 'YYYYMMDD'); -- 删除对应分区(兼容分区不存在的情况) EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(v_drop_part_name) || ';'; END IF; END; $function$;
关键修改点:
- 修复删除分区语法:新增变量存储最大reg_dt和目标分区名,通过
EXECUTE ... INTO安全获取主表最大日期,再计算并拼接分区名执行删除。 - 替换硬编码表名:将终止锁进程逻辑中的固定表名改为函数参数,让函数可复用在同结构的其他分区表上。
- 规范日期运算:把
now()+'1day'改为标准语法now() + interval '1 day',避免语法兼容问题。 - 增强安全性:使用
quote_ident()处理对象名,避免特殊字符导致的语法错误或注入风险。 - 提升健壮性:增加空值判断(主表无数据时跳过删除),使用
DROP TABLE IF EXISTS避免分区不存在时报错。
内容的提问来源于stack exchange,提问作者DBA_Junior
相关产品推荐
相关产品推荐

