查询以返回查询,表或视图的输出列名称和数据类型


21

是否有PostgreSQL查询或命令返回查询,表或视图的字段名称和字段类型?

例如,如果将解决方案应用于简单的SELECT查询,SELECT * from person则应返回如下列表:

Column Name   | Column Type
===========================
First Name    | character
Last Name     | character
Age           | integer
Date of Birth | date

我已经查看了information_schema以下答案中描述的视图,它似乎很好地覆盖了表格,并且我怀疑它也覆盖了视图,但是我还没有检查过。

最后一个是任意但有效的SELECT查询,例如,数据库上的JOINSUNIONS等。是否有内置过程或其他存储过程或脚本可以对任何有效的QUERY完全返回相同的内容?

我正在开发一个用于创建数据和查询表单的程序,该信息对于数据验证和对返回的数据执行功能是必需的。


显然,没有单个“命令”,但是有多种方法可以从系统目录中检索信息。请提出一个具体问题,添加一个示例以及您期望得到的回报,并向我们提供有关其意图的想法。
Erwin Brandstetter 2014年

1
简单的原因是,就客户端而言,查询(即SELECT查询,即非数据定义查询或数据操作查询),无论是在表,视图还是其他查询上,都返回数据的行和列,因此PostgreSQL应该能够返回列名称及其数据类型的列表。information_schema答案中下面提到的视图似乎可以回答表格和视图。任意SELECT查询是最后的领域。我将编辑答案以更好地解释
vfclists 2014年

Answers:


22

信息模式系统目录

我们对此进行了多次讨论。信息模式用于某些目的。如果您了解系统目录的方法,那么IMO 可以更好地满足大多数目的。系统目录是所有信息的实际来源。

信息架构提供了标准化的意见,帮助与便携性,主要是跨主要的Postgres版本,因为在不同的关系型数据库平台的可移植性通常是一种假象,一旦你的查询是复杂的,足以需要查找系统目录。而且,值得注意的是,Oracle仍然不支持信息模式。

信息模式中的视图必须跳很多圈,以实现符合标准的格式。这使它们变慢,有时非常慢。比较这些基本对象的计划和性能:

EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;

区别是明显的。这实际上取决于您要查找的内容。

你的例子

对于您的示例SELECT * from tbl,请比较下面针对此简单表的两个查询:

CREATE TEMP TABLE foo(
   A numeric(12,3)
 , b timestamp(0)
);

使用pg_attribute

SELECT attname, format_type(atttypid, atttypmod) AS type
FROM   pg_attribute
WHERE  attrelid = 'foo'::regclass
AND    attnum > 0
AND    NOT attisdropped
ORDER  BY attnum;

format_type() 返回带有所有修饰符的完整类型:

attname | type
--------+-------------------------------
a       | numeric(12,3)
b       | timestamp(0) without time zone

还要注意,regclass强制类型转换为根据当前可以智能地解析表名search_path。如果名称无效,也会引发异常。细节:

使用information_schema.columns

SELECT column_name, data_type
FROM   information_schema.columns
WHERE  table_name = 'foo'
ORDER  BY ordinal_position;

信息是标准化的,但不完整

column_name | data_type
------------+----------------------------
a           | numeric
b           | timestamp without time zone

为了获得有关数据类型的完整信息,您需要另外考虑所有这些列:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

相关答案:

优点和缺点列表,粗体字的最大优点(IMO):

信息架构视图

  • 通常更简单(取决于)
  • 预处理,可能会或可能不会满足您的需求
  • 选择性的(用户仅看到他们具有特权的对象)
  • 符合SQL标准(由一些主要的RDBMS实施)
  • 大部分可移植到主要的Postgres版本中
  • 不需要有关Postgres的专门知识
  • 标识符是描述性的,冗长的,有时会很尴尬

系统目录

  • 通常更复杂(取决于),更接近源
  • 快速
  • 完成oid包括类似的系统列)
  • 不符合SQL标准
  • 在主要Postgres版本中的可移植性较差(但基础不会改变)
  • 需要有关Postgres的更具体的知识
  • 标识符简洁,描述性较低,但方便使用

任意查询

要从查询中获取相同的列名和类型列表,可以使用一个简单的技巧:从查询输出中创建一个临时表,然后使用与上述相同的技术。

您可以追加LIMIT 0,因为您不需要实际数据:

CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT  0;

要获取各个列的数据类型,还可以使用函数pg_typeof()

SELECT pg_typeof(1);

非常感谢。我一直在研究如何在pg_attribute中获取列的数据类型,并且刚刚遇到了这篇文章。感谢您的帖子。
Melinda

通常,这很有用,但不能回答有关如何获取SELECT语句提供的列的数据类型信息的原始问题。它与视图或表的列无关,它们当然位于系统目录中,并且也显示在信息模式中。
Holger Jakobs


2

如果您可以访问pg_catalog并使用PgAdmin3,我强烈建议您在Valentine's Tech博客(http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields)上找到一种解决方案。 html)。它是一个PgAdmin3宏,可以使用快捷方式访问该宏,以显示所选表名的定义。

select quote_ident(nspname) || '.' || quote_ident(relname) as table_name, 
       quote_ident(attname) as field_name, 
       format_type(atttypid,atttypmod) as field_type, 
       case when attnotnull then ' NOT NULL' else '' end as null_constraint,
       case when atthasdef then 'DEFAULT ' || 
                                ( select pg_get_expr(adbin, attrelid) 
                                    from pg_attrdef 
                                   where adrelid = attrelid and adnum = attnum )::text else ''
       end as dafault_value,
       case when nullif(confrelid, 0) is not null
            then confrelid::regclass::text || '( ' || 
                 array_to_string( ARRAY( select quote_ident( fa.attname ) 
                                           from pg_attribute as fa 
                                          where fa.attnum = ANY ( confkey ) 
                                            and fa.attrelid = confrelid
                                          order by fa.attnum 
                                        ), ','
                                 ) || ' )'
            else '' end as references_to
  from pg_attribute 
       left outer join pg_constraint on conrelid = attrelid 
                                    and attnum = conkey[1] 
                                    and array_upper( conkey, 1 ) = 1,
       pg_class, 
       pg_namespace
 where pg_class.oid = attrelid
   and pg_namespace.oid = relnamespace
   and pg_class.oid = btrim( '$SELECTION$' )::regclass::oid
   and attnum > 0
   and not attisdropped
 order by attrelid, attnum;

就像魅力一样,极其有用。


1

使用information_schema意见,他们是SQL标准,并包含你想要的信息。

您也可以直接访问pg_classpg_attribute等,但这是不可移植的,而且通常比较麻烦;你可能需要像辅助功能oidvectortypespg_get_function_arguments等等一些东西。

如果您想查看psql类似的执行方式\dt,请运行psql -E-它会打印查询。但是,information_schema如果可以满足需要,通常最好使用。


1

这可能过于简单,但是pgAdmin4会在输出结果中显示字段类型。上面的其他解决方案可能更优雅,但是当我只需要快速回答时,我发现pgAdmin4的查询GUI效果很好。试图找出视图或函数返回的计算字段的字段类型可能很棘手。

在此处输入图片说明


pgAdmin4可以很好地做到这一点,但是它是如何做到的呢?我们无需扫描PgAdmin4的所有源代码就能找到答案吗?
Holger Jakobs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.