如何通过PostgreSQL触发器从表字段自动创建多个视图?
解决方案
一、一次性创建所有现有Type对应的视图
用PostgreSQL动态SQL结合DO代码块,循环生成并执行创建视图的语句,一次性搞定现有所有唯一type对应的视图:
DO $$ DECLARE rec record; BEGIN -- 遍历表中所有唯一的type值 FOR rec IN SELECT DISTINCT type FROM mylist LOOP -- 生成合法视图名,自动处理特殊字符,比如把"Big Fish"转为mylist_big_fish EXECUTE format( 'CREATE OR REPLACE VIEW %I AS SELECT * FROM mylist WHERE type = %L;', 'mylist_' || regexp_replace(lower(rec.type), '[^a-z0-9]', '_', 'g'), rec.type ); END LOOP; END $$;
代码说明:
format()函数安全拼接SQL语句,彻底避免SQL注入风险%I自动处理视图名中的非法字符,确保符合PostgreSQL标识符规则%L自动给type值添加引号,避免语法错误regexp_replace()把type中的非字母数字字符替换成下划线,保证视图名合法
二、自动维护视图(新增Type时自动创建)
如果需要在mylist表中新增从未出现过的type值时,自动创建对应的视图,可以通过触发器实现:
1. 先创建触发器函数
CREATE OR REPLACE FUNCTION auto_create_type_view() RETURNS TRIGGER AS $$ DECLARE v_view_name text := 'mylist_' || regexp_replace(lower(NEW.type), '[^a-z0-9]', '_', 'g'); BEGIN -- 先检查视图是否已存在,不存在才创建 IF NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = v_view_name) THEN EXECUTE format( 'CREATE VIEW %I AS SELECT * FROM mylist WHERE type = %L;', v_view_name, NEW.type ); END IF; RETURN NEW; END $$ LANGUAGE plpgsql;
2. 再创建触发器
CREATE TRIGGER trigger_auto_create_type_view AFTER INSERT ON mylist FOR EACH ROW -- 仅当插入的type是表中首次出现时触发,避免重复执行 WHEN (NOT EXISTS (SELECT 1 FROM mylist WHERE type = NEW.type AND id != NEW.id)) EXECUTE FUNCTION auto_create_type_view();
说明:
- 触发器的
WHEN条件确保只有新type值插入时才触发创建逻辑,不会重复操作 - 如果后续需要删除type对应的视图,可以类似编写删除逻辑的触发器,但操作前请确认业务需求,避免误删
内容的提问来源于stack exchange,提问作者Julien
相关产品推荐
相关产品推荐

