PostgreSQL用函数批量改指定catalog所有表所有者报42P01如何解决
错误原因
- PL/pgSQL 的静态 SQL 语句不会自动解析变量为标识符值,你代码中的
ALTER TABLE table_name_value OWNER TO owner_arg语句,会直接将table_name_value当做实际存在的表名进行查找,而非读取该变量存储的真实表名,因此触发「关系不存在」的报错。 - 直接拼接变量执行DDL还存在SQL注入风险,遇到含特殊字符、关键字的表名也会执行失败。
修复方案
改用动态SQL执行ALTER语句,使用format函数的%I占位符自动处理标识符转义,修复后的完整函数代码如下:
CREATE OR REPLACE function change_owner_table_catalog(catalog_arg varchar, owner_arg varchar) RETURNS void AS $$ DECLARE table_name_value varchar; BEGIN for table_name_value in (SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_catalog = catalog_arg) loop -- 改用EXECUTE执行动态SQL,%I为标识符占位符,自动处理转义 EXECUTE format('ALTER TABLE %I OWNER TO %I', table_name_value, owner_arg); end loop; END; $$ language plpgsql;
修复后使用原有调用语句即可正常执行:
select change_owner_table_catalog('cinema', 'cinema_user');
补充说明:你原代码中定义的
sequence_name_value变量未被使用,如果需要同时修改该catalog下序列的所有者,可以新增对应的循环逻辑处理即可。
内容的提问来源于stack exchange,提问作者denis
相关产品推荐
相关产品推荐

