17

我有一个项目,我需要一个查询来使用表名获取列的所有属性(列名、位置、数据类型、Not Null?和评论)。

我实现了获取列名、位置数据类型和 Not Null?使用此查询:

SELECT column_name, data_type, ordinal_position, is_nullable 
FROM information_schema."columns"
WHERE "table_name"='TABLE-NAME'

但是,我需要评论!

4

3 回答 3

28

这是针对系统目录的查询,它应该获取您需要的所有内容(免费提供一个额外的主键字段)。

SELECT DISTINCT
    a.attnum as num,
    a.attname as name,
    format_type(a.atttypid, a.atttypmod) as typ,
    a.attnotnull as notnull, 
    com.description as comment,
    coalesce(i.indisprimary,false) as primary_key,
    def.adsrc as default
FROM pg_attribute a 
JOIN pg_class pgc ON pgc.oid = a.attrelid
LEFT JOIN pg_index i ON 
    (pgc.oid = i.indrelid AND i.indkey[0] = a.attnum)
LEFT JOIN pg_description com on 
    (pgc.oid = com.objoid AND a.attnum = com.objsubid)
LEFT JOIN pg_attrdef def ON 
    (a.attrelid = def.adrelid AND a.attnum = def.adnum)
WHERE a.attnum > 0 AND pgc.oid = a.attrelid
AND pg_table_is_visible(pgc.oid)
AND NOT a.attisdropped
AND pgc.relname = 'TABLE_NAME'  -- Your table name here
ORDER BY a.attnum;

这将返回如下结果:

 num |    name     |             typ             | notnull |       comment       | primary_key 
-----+-------------+-----------------------------+---------+---------------------+-------------
   1 | id          | integer                     | t       | a primary key thing | t
   2 | ref         | text                        | f       |                     | f
   3 | created     | timestamp without time zone | t       |                     | f
   4 | modified    | timestamp without time zone | t       |                     | f
   5 | name        | text                        | t       |                     | f
  • num:列号
  • name:列名
  • 类型:数据类型
  • notnull:列是否定义为NOT NULL
  • 注释:COMMENT为列定义的任何内容
  • primary_key:列是否定义为PRIMARY KEY
  • default:用于默认值的命令
于 2013-04-10T14:37:27.033 回答
5

建立在@Chris 的答案之上

SELECT a.attnum
      ,a.attname                            AS name
      ,format_type(a.atttypid, a.atttypmod) AS typ
      ,a.attnotnull                         AS notnull
      ,coalesce(p.indisprimary, FALSE)      AS primary_key
      ,f.adsrc                              AS default_val
      ,d.description                        AS col_comment
FROM   pg_attribute    a 
LEFT   JOIN pg_index   p ON p.indrelid = a.attrelid AND a.attnum = ANY(p.indkey)
LEFT   JOIN pg_description d ON d.objoid  = a.attrelid AND d.objsubid = a.attnum
LEFT   JOIN pg_attrdef f ON f.adrelid = a.attrelid  AND f.adnum = a.attnum
WHERE  a.attnum > 0
AND    NOT a.attisdropped
AND    a.attrelid = 'schema.tbl'::regclass  -- table may be schema-qualified
ORDER  BY a.attnum;

但:

表名在数据库中不是唯一的,因此在系统目录中也不是唯一的。您可能必须对名称进行模式限定。作为条件
使用。a.attrelid = 'tbl'::regclass这样,您可以myschema.mytbl作为名称传递并消除歧义。那么在这种情况下根本不需要加入pg_class
此外,会自动检查可见性,regclass不需要pg_table_is_visible().

一个主键可以跨越多个列。我通过加入pg_indexon来解决这个问题a.attnum = ANY(p.indkey)
indkey是 的类型int2vecor,是 的特例int2[],仅在目录中使用。

我发现psql -E对这类问题很有帮助。

兼容性

像这样的专门查询可能会在主要版本更新后中断。Postgres 不保证目录表保持稳定。基本元素改变的可能性极小,但是查询越复杂和专业,机会就越大。您可以改用信息模式,它是标准化的,但也相对较慢。

于 2013-04-10T16:36:04.523 回答
0

我认为你可以使用这个:

select ordinal_position AS num, column_name as name, data_type as typ, character_maximum_length as lenth, 
is_nullable as nullable, column_default as default
from INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog='DatabaseName' AND table_name='TableName'
于 2020-03-02T02:13:13.393 回答