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 这张表的字段类型和数据
sql
-- 取字段名和字段类型
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 | 如果列是域类型的基础类型,则是基础类型的名称。 |
sql
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:
sql
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
类型。attrelid
是pg_attribute
表中的一个字段,表示属性(列)所属的表的 OID。
所以,attrelid = 'adb_task_daily_detail_log'::regclass
这个条件是在过滤 pg_attribute
表的记录,只选择属于名为 'adb_task_daily_detail_log'
的表的记录。
这样做是因为在 PostgreSQL 中,每个表都有一个唯一的 OID,而 pg_attribute
表存储了关于表的每个列的信息。通过检查 attrelid
,我们可以限制结果只包括特定表的列信息。