【问题标题】:Retrieving Comments from a PostgreSQL DB从 PostgreSQL 数据库中检索评论
【发布时间】:2010-09-25 11:33:32
【问题描述】:

我正在 Postgres 数据库上运行一个项目,需要检索数据库中列上的 cmets 以用作表标题等。我已经看到有几个内置函数(pg_descriptioncol_description),但我无法找到有关如何使用它们的示例,并且使用它们被证明是徒劳的。

所以我想知道之前是否有人能够做到这一点,如果可以,怎么做?

【问题讨论】:

  • PostgreSQL 不是很友好,但这是因为每个用户都有你个人的(非标准的)“util library”。在我的库的一个函数(rel_description)下面,可以帮助你。

标签: postgresql metadata


【解决方案1】:
SELECT c.table_schema,c.table_name,c.column_name,pgd.description
FROM pg_catalog.pg_statio_all_tables as st
  inner join pg_catalog.pg_description pgd on (pgd.objoid=st.relid)
  inner join information_schema.columns c on (pgd.objsubid=c.ordinal_position
    and  c.table_schema=st.schemaname and c.table_name=st.relname);

【讨论】:

  • 我不太明白这段代码是如何工作的,但它可以满足我的需要,所以我不必这样做。
  • 我遇到了一个案例,肯定有表格,结果集的大小为 0。有些事情不太对劲
  • 效果很好,但查询很复杂。
  • pg_statio_all_tables 是重视图,因此不要将其用于检索列描述。很好的解决方案是“T.Z.”的回答。
  • 按表名过滤并按行数排序: where table_name='parametros_gestora_academica' order by c.ordinal_position ;
【解决方案2】:

这一切都由oid工作,

mat=> SELECT c.oid FROM pg_catalog.pg_class c WHERE c.relname = 'customers';
  oid  
-------
 23208
(1 row)

现在,我有那个表的 oid,所以我可以问:

mat=> select pg_catalog.obj_description(23208);
  obj_description  
-------------------
 Customers
(1 row)

那么,我可以询问第四列的描述:

mat=> select pg_catalog.col_description(23208,4);
             col_description             
-----------------------------------------
 Customer codes, CHS, FACTPOST, POWER...
(1 row)

如果您想知道 psql 在您执行 \dt+\d+ customers 时运行哪些查询,只需使用 -E 运行即可。

【讨论】:

【解决方案3】:

注意架构,这段代码会考虑它们:

SELECT
    cols.column_name, (
        SELECT
            pg_catalog.col_description(c.oid, cols.ordinal_position::int)
        FROM
            pg_catalog.pg_class c
        WHERE
            c.oid = (SELECT ('"' || cols.table_name || '"')::regclass::oid)
            AND c.relname = cols.table_name
    ) AS column_comment
FROM
    information_schema.columns cols
WHERE
    cols.table_catalog    = 'your_database'
    AND cols.table_name   = 'your_table'
    AND cols.table_schema = 'your_schema';

参考资料:

【讨论】:

  • 以下行允许表名的更多灵活性:c.oid = (SELECT ('"' || cols.table_name || '"')::regclass::oid) AND
  • @jcristovao,你能解释得更好吗?
  • 我使用该行以便在WHERE 子句中只指定一次table_name。但是,cols.table_name 的简单解决方案以 WeirdCaps 之类的表名失败
  • @MarcioMazzucato:参见postgresql.org/docs/current/datatype-oid.htmlregclass 类型将字符串作为输入并为其找到相应的对象 OID。
【解决方案4】:

只要有人需要,就在这里。

这里有很多答案,但没有一个像我希望的那样简单。因此,基于以前的答案和当前的 postgres 9.4,我创建了这个查询:

SELECT 
    obj_description(format('%s.%s',isc.table_schema,isc.table_name)::regclass::oid, 'pg_class') as table_description,
    pg_catalog.col_description(format('%s.%s',isc.table_schema,isc.table_name)::regclass::oid,isc.ordinal_position) as column_description
FROM
    information_schema.columns isc

它获取表和列描述,没有任何令人困惑的连接和丑陋的字符串连接。

【讨论】:

    【解决方案5】:

    这适用于我使用 PostBooks 3.2.2 DB:

    select cols.column_name,
    (select pg_catalog.obj_description(oid) from pg_catalog.pg_class c where c.relname=cols.table_name) as table_comment
    ,(select pg_catalog.col_description(oid,cols.ordinal_position::int) from pg_catalog.pg_class c where c.relname=cols.table_name) as column_comment
    from information_schema.columns cols
    where cols.table_catalog='postbooks' and cols.table_name='apapply'
    

    问候, 合成器

    【讨论】:

    • 它可以工作,但是 Postgres 文档中的一个小注释: obj_description 的单参数形式只需要对象 OID。现在不推荐使用它,因为不能保证 OID 在不同的系统目录中是唯一的;因此,可能会返回错误的评论。
    【解决方案6】:

    对其他答案之一稍作更改,它只会为您提供包含 cmets 的列,这将为您提供所有列,无论它们是否有评论。

    select c.table_schema, st.relname as TableName, c.column_name, 
    pgd.description
    from pg_catalog.pg_statio_all_tables as st
    inner join information_schema.columns c
    on c.table_schema = st.schemaname
    and c.table_name = st.relname
    left join pg_catalog.pg_description pgd
    on pgd.objoid=st.relid
    and pgd.objsubid=c.ordinal_position
    where st.relname = 'YourTableName';
    

    【讨论】:

    • 谢谢,相当于Oracle中的user_col_cmets
    • 这对我来说效果最好,并且能够正确处理混合大小写的表和模式名称。干杯!
    【解决方案7】:

    增强@Nick 和@mat 建议:使用
    SELECT obj_description('schemaName.tableName'::regclass, 'pg_class'); 当你有字符串名称(不是 oid)时。

    为了避免记住 'pg_class' 参数,并避免在函数调用时出现丑陋的连接,如 (tname||'.'||schema)::regclassobj_description 的有用重载:

      CREATE FUNCTION obj_description(
          p_rname text, p_schema text DEFAULT NULL, 
          p_catalname text DEFAULT 'pg_class'
      ) RETURNS text AS $f$
         SELECT obj_description((CASE 
            WHEN strpos($1, '.')>0 OR $2 IS NULL OR $2='' THEN $1
            ELSE $2||'.'||$1
         END)::regclass, $3);
      $f$ LANGUAGE SQL IMMUTABLE;
     -- USAGE: obj_description('mytable') 
     --        SELECT obj_description('s.t'); 
     -- PS: obj_description('s.t', 'otherschema') is a syntax error, 
     --     but not generates exception: returns the same as ('s.t') 
    

    现在很容易使用,因为 表名rname 参数)是一个 varchar,可以用 schema name 的分隔字段来表示,如主表和查询。

    另见“Getting list of table comments in PostgreSQL”或new pg9.3 Guide

    【讨论】:

      【解决方案8】:

      这个答案有点晚了,但它出现在我为研究这个问题所做的谷歌搜索中。我们只需要表格描述,但列的方法是相同的。 列描述也在 pg_description 表中,由 objoid 引用。

      添加此视图:

      
      CREATE OR REPLACE VIEW our_tables AS 
       SELECT c.oid, n.nspname AS schemaname, c.relname AS tablename, d.description,
         pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS "tablespace", 
         c.relhasindex AS hasindexes, c.relhasrules AS hasrules, c.reltriggers > 0 AS hastriggers
         FROM pg_class c
         LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
         LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
         LEFT JOIN pg_description d ON c.oid = d.objoid
        WHERE c.relkind = 'r'::"char";
      
      ALTER TABLE our_tables OWNER TO postgres;
      GRANT SELECT, UPDATE, INSERT, DELETE, REFERENCES, TRIGGER ON TABLE our_tables TO postgres;
      GRANT SELECT ON TABLE our_tables TO public;
      
      

      然后运行:

      SELECT tablename, description FROM our_tables WHERE schemaname = 'public'

      该视图是 pg_tables 视图的修改版本,它添加在描述列中。 您还可以随意使用视图定义以使其成为单个查询。

      【讨论】:

        【解决方案9】:

        我这样访问表 cmets:

        select c.relname table_name, pg_catalog.obj_description(c.oid) as comment from pg_catalog.pg_class c where c.relname = 'table_name';
        

        因此列 cmets:

        SELECT c.column_name, pgd.description FROM pg_catalog.pg_statio_all_tables as st inner join pg_catalog.pg_description pgd on (pgd.objoid=st.relid) inner join information_schema.columns c on (pgd.objsubid=c.ordinal_position and c.table_schema=st.schemaname and c.table_name=st.relname and c.table_name = 'table_name' and c.table_schema = 'public');
        

        【讨论】:

          【解决方案10】:

          如果您只需要在其他数据中为您的列显示comments,您也可以使用:

          \d+ my_table
          

          【讨论】:

            【解决方案11】:

            我刚刚在这里找到了这个。它将为您提供一个特定表上的所有类型的元数据(类型、默认值、非空标志、长度、注释、外键名称、主键名称)。它似乎运作良好。

            SELECT pg_tables.tablename, pg_attribute.attname AS field, 
                format_type(pg_attribute.atttypid, NULL) AS "type", 
                pg_attribute.atttypmod AS len,
                (SELECT col_description(pg_attribute.attrelid, 
                        pg_attribute.attnum)) AS comment, 
                CASE pg_attribute.attnotnull 
                    WHEN false THEN 1  ELSE 0  
                END AS "notnull", 
                pg_constraint.conname AS "key", pc2.conname AS ckey, 
                (SELECT pg_attrdef.adsrc FROM pg_attrdef 
                    WHERE pg_attrdef.adrelid = pg_class.oid 
                    AND pg_attrdef.adnum = pg_attribute.attnum) AS def 
            FROM pg_tables, pg_class 
            JOIN pg_attribute ON pg_class.oid = pg_attribute.attrelid 
                AND pg_attribute.attnum > 0 
            LEFT JOIN pg_constraint ON pg_constraint.contype = 'p'::"char" 
                AND pg_constraint.conrelid = pg_class.oid AND
                (pg_attribute.attnum = ANY (pg_constraint.conkey)) 
            LEFT JOIN pg_constraint AS pc2 ON pc2.contype = 'f'::"char" 
                AND pc2.conrelid = pg_class.oid 
                AND (pg_attribute.attnum = ANY (pc2.conkey)) 
            WHERE pg_class.relname = pg_tables.tablename  
            --    AND pg_tables.tableowner = "current_user"() 
                AND pg_attribute.atttypid <> 0::oid  
                AND tablename='your_table' 
            ORDER BY field ASC
            

            来源:http://golden13.blogspot.de/2012/08/how-to-get-some-information-about_7.html

            【讨论】:

              【解决方案12】:

              好的,所以我解决了这个问题......

              选择 col_description(表 id, 列号)...

              即:选择 col_description(36698,2);

              这行得通,但是有没有更简单的方法可以做到这一点,也许将所有的 cmets 放在所有列上,并使用表名而不是 oid ???

              【讨论】:

                【解决方案13】:

                我上个月问过a similar question about Postgresql comments。如果你仔细研究,你会在我的博客上看到一些 Perl 代码,它可以自动提取评论。

                要提取表的列名,可以使用以下内容:

                select
                     a.attname  as "colname"
                    ,a.attrelid as "tableoid"
                    ,a.attnum   as "columnoid"
                from
                    pg_catalog.pg_attribute a
                    inner join pg_catalog.pg_class c on a.attrelid = c.oid
                where
                        c.relname = 'mytable' -- better to use a placeholder
                    and a.attnum > 0
                    and a.attisdropped is false
                    and pg_catalog.pg_table_is_visible(c.oid)
                order by a.attnum
                

                然后您可以使用 tableoid,columnoid 元组来提取每列的注释(请参阅我的问题)。

                【讨论】:

                  【解决方案14】:

                  显示所有表中所有列的 cmets:

                  SELECT
                      cols.table_name,
                      cols.column_name, (
                      SELECT
                          pg_catalog.col_description(c.oid, cols.ordinal_position::int)
                      FROM
                          pg_catalog.pg_class c
                      WHERE
                              c.oid = (SELECT ('"' || cols.table_name || '"')::regclass::oid)
                        AND c.relname = cols.table_name
                  ) AS column_comment
                  FROM
                      information_schema.columns cols
                  WHERE
                    cols.table_name   IN (SELECT cols.table_name FROM information_schema.columns)
                    AND cols.table_catalog = 'your_database_name'
                    AND cols.table_schema = 'your_schema_name';
                  

                  您需要在任何架构/目录/数据库之外执行此查询

                  此查询基于此问题中的另一个答案,该答案仅显示来自一个表的 cmets

                  【讨论】:

                    【解决方案15】:

                    扩展@amxy 提供的响应;我发现添加模式过滤器在某些环境中会有所帮助。我发现@amxy 的解决方案在我通过模式过滤器添加之前不起作用

                    SELECT 
                    pg_tables.schemaname,
                    pg_tables.TABLENAME,
                    pg_attribute.attname AS field,
                    format_type(pg_attribute.atttypid, NULL) AS "type",
                    pg_attribute.atttypmod AS len,
                    (
                    SELECT col_description(pg_attribute.attrelid, pg_attribute.attnum)) AS  COMMENT,
                    CASE pg_attribute.attnotnull
                        WHEN FALSE THEN 1
                        ELSE 0
                    END AS "notnull",
                    pg_constraint.conname AS "key", pc2.conname AS ckey,
                    (
                    SELECT pg_attrdef.adsrc
                    FROM pg_attrdef
                    WHERE pg_attrdef.adrelid = pg_class.oid
                        AND pg_attrdef.adnum = pg_attribute.attnum) AS def
                    FROM pg_tables, pg_class
                    JOIN pg_attribute
                        ON pg_class.oid = pg_attribute.attrelid
                        AND pg_attribute.attnum > 0
                    LEFT JOIN pg_constraint
                        ON pg_constraint.contype = 'p'::"char"
                        AND pg_constraint.conrelid = pg_class.oid
                        AND
                    (pg_attribute.attnum = ANY (pg_constraint.conkey))
                    LEFT JOIN pg_constraint AS pc2
                        ON pc2.contype = 'f'::"char"
                        AND pc2.conrelid = pg_class.oid
                        AND (pg_attribute.attnum = ANY (pc2.conkey))
                    WHERE pg_class.relname = pg_tables.TABLENAME
                    AND pg_tables.schemaname IN ('op', 'im', 'cs','usr','li')
                    -- AND pg_tables.tableowner = "current_user"()
                        AND pg_attribute.atttypid <> 0::oid
                        ---AND TABLENAME='your_table'
                    ORDER BY pg_tables.schemaname,
                    pg_tables.TABLENAME ASC;
                    

                    结果:

                    【讨论】:

                      猜你喜欢
                      • 2011-03-21
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-03-02
                      • 1970-01-01
                      • 2012-03-23
                      • 1970-01-01
                      • 2011-11-04
                      相关资源
                      最近更新 更多