postpresql 查询某张表的字段名和字段类型

postpresql 查询某张表的字段名和字段类型

工作中第一次接触postpresql,接触到这么个需求,只是对sql有点了解,于是就网上查阅资料。得知通过系统表可以查询,设计到几张系统表:pg_class、pg_attrubute、information_schema.columns 。

其中pg_class 这张表记录了所有表或者像表的东西。包括表、索引、视图、物化视图、组合类型和TOAST表。其中一些字段的含义如下表所示。

​ pg_class

字段名 字段描述
oid 表的唯一标识符(Object ID)
relname 表的名称
relnamespace 表所属的命名空间(pg_namespace 表的 oid)
reltype 表的类型。对于表,这通常是 pg_type 表中的 oid
reloftype 对于复合类型的表,它表示相关联的基础类型
relowner 表的所有者(用户的 oid)
relam 索引使用的存储方法的 oid
relfilenode 表在磁盘上的文件节点号
reltablespace 表所在的表空间的 oid
relpages 表占用的页数
reltuples 表中的元组数。
reltoastrelid 如果存在,指向 pg_class 中的 TOAST 表的 oid
reltoastidxid 如果存在,指向 TOAST 表的索引的 oid
relhasindex 表是否有索引
relisshared 表是否是共享的
relpersistence 表的持久性(永久的还是临时的)
relkind 表的类型,可能是 ‘r’(表)、‘i’(索引)等
relchecks 表约束的数量
reltriggers 表触发器的数量
relhasrules 表是否有规则
relhasoids 表是否有 OIDs(Object Identifiers)

pg_attrubute

这张表包含了有关表的每一列的详细信息,例如数据类型、是否为空等。

字段名 字段描述
attrelid: 属性所属的表的 OID。
attname: 列名。
atttypid 列的数据类型的 OID,对应于 pg_type 表中的 oid。
attstattarget 用于统计信息的目标值。
attlen 列的长度(以字节为单位)。
attnum 列的序号。正整数表示用户定义的列,0 表示系统列。
attndims 数组的维数,如果不是数组则为 0。
attcacheoff 用于计算偏移量的缓存位置。
atttypmod 类型修饰符。对于 varchar(n) 这样的类型,它存储 n 的值。
attbyval 如果列的传递是按值传递,则为 true;否则为 false。
attstorage 列的存储方式(‘p’ 表示普通、‘e’ 表示外部、‘m’ 表示主内存)。
attalign 列的对齐方式(‘c’ 表示 CHAR、‘s’ 表示 SHORT、‘i’ 表示 INT、‘d’ 表示 DOUBLE)。
attnotnull 如果列不允许为空,则为 true;否则为 false。
atthasdef 如果列有默认值,则为 true;否则为 false。
attisdropped 如果列已被删除,则为 true;否则为 false。
attislocal 如果列是表的本地列,则为 true;否则为 false。
attinhcount 列是否继承自父表。
attcollation 列的排序规则的 OID。
attacl 列的访问控制列表。
attoptions 列的选项。
attfdwoptions 表示列是否有存储外部化的选项。
attmissingval 缺失值。

原本的想法,或者说是拿到的代码。要查的是adb_task_daily_detail_log 这张表的字段类型和数据

-- 取字段名和字段类型
select
a.attname as name,
format_type(a.atttypid,a.atttypmod) as type,
col_description(a.attrelid,a.attnum) as comment,
a.attnotnull as notnull
from
pg_class as c,
pg_attribute as a
where
c.relname='adb_task_daily_detail_log'
and
a.attrelid=c.oid -- 关联条件
and
a.attnum>0;

问题出现了,对于adb_task_daily_detail_log这张表,pg_class出现了2条记录。

查了半天也搞不懂为什么有两条记录,如果有大哥知道的话请指导下小弟。

有说多一条索引,就会多一条记录,但是这张表也没有索引。

有说表记录了TOAST相关的信息也会多存储一条relkind =‘t’ 的记录,但是这两条记录都是’r’。

所以后果就是查询出来的字段数量会重复。

方式2:

查information_schema.columns

information_schema.columns 是 PostgreSQL 中的系统视图之一,它存储了数据库中所有表的列信息。这个视图允许用户查询表的元数据,包括列名、数据类型、是否为主键、是否允许为空等。

字段名称 字段描述
table_catalog 表所属的数据库名称。
table_schema 表所属的模式(Schema)名称。
table_name 表的名称。
column_name 列的名称。
ordinal_position 列在表中的位置,从 1 开始。
column_default 列的默认值。
is_nullable 如果列允许为 NULL,则为 “YES”;否则为 “NO”。
data_type 列的数据类型。
character_maximum_length 如果数据类型是字符型,则是字符的最大长度。
character_octet_length 字符的八位字节长度。
numeric_precision 如果数据类型是数字型,则是精度。
numeric_precision_radix 数字的基数(通常为 10)。
numeric_scale 如果数据类型是数字型,则是小数点后的位数。
datetime_precision 如果数据类型是日期时间型,则是小数秒的位数。
interval_type 如果数据类型是间隔型,则是间隔类型。
interval_precision 如果数据类型是间隔型,则是间隔的精度。
character_set_catalog 字符集所属的数据库名称。
character_set_schema 字符集所属的模式名称。
character_set_name 字符集的名称。
collation_catalog 校对规则所属的数据库名称。
collation_schem 校对规则所属的模式名称。
collation_name 校对规则的名称。
domain_catalog 如果列是域类型的基础类型,则是基础类型所属的数据库名称。
domain_schema 如果列是域类型的基础类型,则是基础类型所属的模式名称。
domain_name 如果列是域类型的基础类型,则是基础类型的名称。
select 
	column_name
	concat(
  	data_type,
    case 
    	when character_maximum_length is not null then '(' || character_maximum_length || ')'
    	else ''
    end
  ) as type

from information_schema.columns
where table_name ='adb_task_daily_detail_log';

为了要使得数据类型和长度一起显示 做了一个拼接,但是只有字符类型的数据才会被拼接。需求是对数字类型的数字也拼接。

format_type 这个函数得到的数据就是满足要求的。

方式3:

select 
 attname as name
 format_type (atttypeid,atttypmod) as type
 from
 	pg_attribute
 where
 	attrelid ='adb_task_daily_detail_log'::regclass and 
 	attnum>0;
  • ::regclass 是 PostgreSQL 的类型转换语法。它将一个标识符(在这里是字符串 'adb_task_daily_detail_log')转换为 regclass 类型。
  • attrelidpg_attribute 表中的一个字段,表示属性(列)所属的表的 OID。

所以,attrelid = 'adb_task_daily_detail_log'::regclass 这个条件是在过滤 pg_attribute 表的记录,只选择属于名为 'adb_task_daily_detail_log' 的表的记录。

这样做是因为在 PostgreSQL 中,每个表都有一个唯一的 OID,而 pg_attribute 表存储了关于表的每个列的信息。通过检查 attrelid,我们可以限制结果只包括特定表的列信息。

你可能感兴趣的:(postgresql,sql)