PostgreSQL创建自引用复合类型报错的解决方法
当执行以下自引用复合类型创建代码时,PostgreSQL会抛出composite type t_mytype cannot be made a member of itself错误:
CREATE TYPE t_mytype AS ( id uuid ); ALTER TYPE t_mytype ADD ATTRIBUTE children t_mytype[];
该限制来自PostgreSQL的内置类型校验逻辑:复合类型创建阶段需要计算固定的内存布局,直接持有自身类型的成员会触发无限递归的长度计算,因此被默认拦截。针对仅在PL/pgSQL函数内作为入参、做递归结构遍历、不做持久化存储的场景,可以通过以下方案绕过限制。
可行实现方案
使用DOMAIN作为中间代理层穿透自引用校验,该方案完全保留类型安全,使用体验和原生自引用数组无差异:
-- 1. 创建基础复合类型 CREATE TYPE t_mytype AS ( id uuid ); -- 2. 定义DOMAIN作为t_mytype数组的代理别名,该步骤可正常执行,因t_mytype已完成定义 CREATE DOMAIN d_mytype_children AS t_mytype[]; -- 3. 为复合类型添加子节点属性,使用DOMAIN类型绕开直接自引用检查 ALTER TYPE t_mytype ADD ATTRIBUTE children d_mytype_children;
使用说明
- 上述方式定义的类型在PL/pgSQL逻辑中使用时,
children属性的操作逻辑和直接定义为t_mytype[]完全一致,支持数组遍历、递归访问、成员取值等所有常规操作,无需额外做类型转换。 - 该方案仅适配内存中的函数计算场景,不要使用该复合类型创建数据表、存储持久化数据,否则会触发TOAST存储、数据写入阶段的递归处理异常。
- 如果不需要强类型校验,也可以直接将
children属性定义为anyarray类型,递归处理时在函数内部手动强转为t_mytype[]即可,无需创建额外DOMAIN,但该方式无编译期类型检查,容错性更低。
内容的提问来源于stack exchange,提问作者Dewey Vozel
相关产品推荐
相关产品推荐

