PostgreSQL系统表或视图中pg_node_tree类型值解析

PostgreSQL系统表或视图中pg_node_tree类型值解析

pg_node_tree类型说明

pg_node_tree是一种openGauss/PostgreSQL内部数据类型,用于表示树形结构的数据。这个数据类型通常对用户不可见,因此直接查询或操作它的内容通常需要使用一些PostgreSQL的内置函数或工具。

包含pg_node_tree类型的系统视图/表,以pg12版本为例:

postgres=# select table_schema,table_name,column_name from information_schema.columns where data_type = 'pg_node_tree';
 table_schema |      table_name      |  column_name
--------------+----------------------+----------------
 pg_catalog   | pg_proc              | proargdefaults
 pg_catalog   | pg_type              | typdefaultbin
 pg_catalog   | pg_class             | relpartbound
 pg_catalog   | pg_attrdef           | adbin
 pg_catalog   | pg_constraint        | conbin
 pg_catalog   | pg_index             | indexprs
 pg_catalog   | pg_index             | indpred
 pg_catalog   | pg_rewrite           | ev_qual
 pg_catalog   | pg_rewrite           | ev_action
 pg_catalog   | pg_trigger           | tgqual
 pg_catalog   | pg_policy            | polqual
 pg_catalog   | pg_policy            | polwithcheck
 pg_catalog   | pg_partitioned_table | partexprs
(13 rows)

postgres=#

解析对应关系

系统表/视图 字段名 解析使用表达式
pg_proc proargdefaults pg_get_expr(proargdefaults,‘pg_proc’::regclass)
pg_get_function_arguments(oid)
pg_type typdefaultbin
pg_class relpartbound pg_get_expr(relpartbound,oid)
pg_attrdef adbin pg_get_expr(adbin,adrelid)
pg_constraint conbin pg_get_expr(conbin,conrelid)
pg_get_constraintdef(oid)
pg_index indexprs pg_get_expr(indexprs,indrelid)
pg_index indpred pg_get_expr(indpred,indrelid)
pg_rewrite ev_qual
pg_rewrite ev_action
pg_trigger tgqual pg_get_triggerdef(oid)
pg_policy polqual
pg_policy polwithcheck
pg_partitioned_table partexprs pg_get_expr(partexprs,partrelid)

pg_node_tree类型值解析

对于存储再pg_node_tree类型中的数据,可以使用pg_get_expr()函数将其转换为可读的SQL表达式。这个函数将抽象的树形结构转换为一个人类可读的SQL表达式形式。

pg_get_expr函数说明:

pg_get_expr(pg_node_tree, relation_oid)
pg_get_expr(pg_node_tree, relation_oid, pretty_bool)

返回类型:text

反编译一个表达式的内部形式,假定其中的任何 Var 指向由第二个参数指示的关系

解析pg_attrdef.adbin

pg_attrdef存储列的默认值。列的主要信息存储在pg_attribute。只有那些显式指定了一个默认值的列才会在这个目录中有一个项。

-- 创建测试表
drop table if exists test_t;
create table test_t (id int,name varchar(20) default 'test',update_time timestamp default current_timestamp);

-- 原查询结果
select t1.adrelid::regclass,t2.attname,adbin
from pg_attrdef t1
join pg_attribute t2 on t1.adrelid=t2.attrelid and t1.adnum=t2.attnum
where t2.attnum>0
      and t1.adrelid::regclass::text='test_t';
-[ RECORD 1 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
adrelid | test_t
attname | name
adbin   | {FUNCEXPR :funcid 669 :funcresulttype 1043 :funcretset false :funcvariadic false :funcformat 2 :funccollid 100 :inputcollid 100 :args ({CONST :consttype 1043 :consttypmod -1 :constcollid 100 :constlen -1 :constbyval false :constisnull false :location 53 :constvalue 8 [ 32 0 0 0 116 101 115 116 ]} {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ 24 0 0 0 0 0 0 0 ]} {CONST :consttype 16 :consttypmod -1 :constcollid 0 :constlen 1 :constbyval true :constisnull false :location -1 :constvalue 1 [ 0 0 0 0 0 0 0 0 ]}) :location -1}
-[ RECORD 2 ]------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
adrelid | test_t
attname | update_time
adbin   | {FUNCEXPR :funcid 2027 :funcresulttype 1114 :funcretset false :funcvariadic false :funcformat 2 :funccollid 0 :inputcollid 0 :args ({SQLVALUEFUNCTION :op 3 :type 1184 :typmod -1 :location 90}) :location -1}

-- 解析后
select t1.adrelid::regclass,t2.attname,pg_get_expr(adbin,t1.adrelid)
from pg_attrdef t1
join pg_attribute t2 on t1.adrelid=t2.attrelid and t1.adnum=t2.attnum
where t2.attnum>0
      and t1.adrelid::regclass::text='test_t';
 adrelid |   attname   |        pg_get_expr
<
<think> 根据用户提供的信息,错误信息为'ERROR: relation "idx_tree_node_id" already exists',这明尝试创建一个名为"idx_tree_node_id"的索引,但这个索引已经存在。在高斯数据库(GaussDB)中,索引名称必须在同一个schema内唯一。因此,需要定位到哪个已经存在这个索引。 方法步骤: 1. 查询系统pg_indexes,通过索引名idx_tree_node_id来查找对应的名。 2. 在GaussDB中,系统pg_indexes存储了所有索引的信息,包括索引名(indexname)、名(tablename)、模式名(schemaname)等。 具体SQL查询语句如下: ```sql SELECT schemaname, tablename, indexname FROM pg_indexes WHERE indexname = 'idx_tree_node_id'; ``` 执行这个查询就可以知道哪个已经拥有这个索引。 另外,用户之前提供的引用[1]中提到了索引的创建、检查和重建,但并没有直接解决如何查找重复索引名的问题。不过,我们可以借鉴其中查询pg_stat_all_indexes的方法,但这里我们只需要查询pg_indexes。 注意:错误信息中的关系(relation)通常是指、索引、视图等。这里明确是索引已经存在。 如果查询结果为空,可能是索引在另一个数据库中,者大小写问题(GaussDB默认是大小写不敏感的?),但错误信息中给出的索引名是全小写,而GaussDB中默认会将对象名转为小写(除非使用双引号创建了混合大小写的名称)。所以,如果创建时使用了双引号指定了大小写,那么查询时也需要用双引号。但错误信息中的索引名是小写,所以很可能创建时没有使用双引号,因此直接用小写查询即可。 如果确实存在,那么用户需要决定如何处理:可以删除已存在的索引(如果不再需要)者修改新索引的名称。 删除索引的命令: ```sql DROP INDEX CONCURRENTLY IF EXISTS schemaname.idx_tree_node_id; ``` 注意:在删除索引时,使用CONCURRENTLY可以避免长时间锁,但需要注意该选项在GaussDB中的支持情况(GaussDB是华为基于PostgreSQL开发的,通常支持DROP INDEX CONCURRENTLY)。 如果用户仍然想创建同名索引,但又不确定是哪个已经存在,那么必须先删除重命名已存在的索引。 此外,为了避免此类错误,在创建索引之前可以先检查是否存在同名的索引。例如: ```sql DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_tree_node_id' AND schemaname = 'your_schema') THEN RAISE NOTICE 'Index idx_tree_node_id already exists in schema your_schema'; ELSE CREATE INDEX idx_tree_node_id ON your_table (your_column); END IF; END $$; ``` 但是,由于用户已经遇到了错误,所以现在需要先定位问题。 因此,针对用户的问题,直接查询pg_indexes即可。 生成相关问题: 1. 如何避免在创建索引时出现名称重复? 2. 在GaussDB中,如何列出某个的所有索引? 3. 在GaussDB中,如何安全删除一个已经存在的索引? </think> 基于错误信息 `ERROR: relation "idx_tree_node_id" already exists`,在高斯数据库(GaussDB)中定位索引重复的方法如下: ### 定位索引重复的方法 1. **查询系统 `pg_indexes`** 执行以下 SQL,通过索引名直接定位所属: ```sql SELECT schemaname, tablename FROM pg_indexes WHERE indexname = 'idx_tree_node_id'; ``` - `schemaname`:索引所在的模式(如 `public`) - `tablename`:已存在该索引的名 2. **检查所有对象(备用方案)** 若上述查询无结果,可能索引在其他命名空间: ```sql SELECT nspname AS schemaname, relname AS tablename FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = 'idx_tree_node_id' AND c.relkind = 'i'; -- 仅查询索引对象 ``` 3. **验证索引属性** 确认索引细节: ```sql SELECT * FROM pg_indexes WHERE indexname = 'idx_tree_node_id'; ``` 输出包含名、列定义及创建语句。 ### 原因与解决方案 - **原因**:同一数据库内索引名必须唯一,重复创建同名索引会触发此错误。 - **解决方案**: 1. **删除旧索引**(谨慎操作): ```sql DROP INDEX CONCURRENTLY IF EXISTS idx_tree_node_id; ``` 2. **创建新索引时重命名**: ```sql CREATE INDEX CONCURRENTLY idx_tree_node_id_new ON your_table (column_name); ``` ### 操作注意事项 1. 生产环境操作前建议备份 2. 使用 `CONCURRENTLY` 避免锁 3. 检查索引是否被依赖(如外键): ```sql SELECT * FROM pg_depend WHERE objid = 'idx_tree_node_id'::regclass; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值