【问题标题】:Is there a way to show a user-defined postgresql enumerated type definition?有没有办法显示用户定义的 postgresql 枚举类型定义?
【发布时间】:2012-03-21 02:41:27
【问题描述】:

假设我们定义了一个 postgresql 类型:

CREATE TYPE my_type AS ENUM('foo', 'bar');

有什么方法可以在创建后显示类型定义?

我希望“\d my_type”向我显示“ENUM('foo', 'bar')”,但它说:

Did not find any relation named "my_type"

pg_type 表似乎没有提供足够的信息。

【问题讨论】:

    标签: postgresql enums


    【解决方案1】:

    使用this post,我已经归档了在 PgAdmin 和 PgBackup 中模仿“CREATE TYPE”的目标

    WITH types AS (
        SELECT n.nspname,
                pg_catalog.format_type ( t.oid, NULL ) AS obj_name,
                CASE
                    WHEN t.typrelid != 0 THEN CAST ( 'tuple' AS pg_catalog.text )
                    WHEN t.typlen < 0 THEN CAST ( 'var' AS pg_catalog.text )
                    ELSE CAST ( t.typlen AS pg_catalog.text )
                    END AS obj_type,
                coalesce ( pg_catalog.obj_description ( t.oid, 'pg_type' ), '' ) AS description
            FROM pg_catalog.pg_type t
            JOIN pg_catalog.pg_namespace n
                ON n.oid = t.typnamespace
            WHERE ( t.typrelid = 0
                    OR ( SELECT c.relkind = 'c'
                            FROM pg_catalog.pg_class c
                            WHERE c.oid = t.typrelid ) )
                AND NOT EXISTS (
                        SELECT 1
                            FROM pg_catalog.pg_type el
                            WHERE el.oid = t.typelem
                            AND el.typarray = t.oid )
                AND n.nspname <> 'pg_catalog'
                AND n.nspname <> 'information_schema'
                AND n.nspname !~ '^pg_toast'
    ),
    cols AS (
        SELECT n.nspname::text AS schema_name,
                pg_catalog.format_type ( t.oid, NULL ) AS obj_name,
                a.attname::text AS column_name,
                pg_catalog.format_type ( a.atttypid, a.atttypmod ) AS data_type,
                a.attnotnull AS is_required,
                a.attnum AS ordinal_position,
                pg_catalog.col_description ( a.attrelid, a.attnum ) AS description
            FROM pg_catalog.pg_attribute a
            JOIN pg_catalog.pg_type t
                ON a.attrelid = t.typrelid
            JOIN pg_catalog.pg_namespace n
                ON ( n.oid = t.typnamespace )
            JOIN types
                ON ( types.nspname = n.nspname
                    AND types.obj_name = pg_catalog.format_type ( t.oid, NULL ) )
            WHERE a.attnum > 0
                AND NOT a.attisdropped
    )
    SELECT 'CREATE TYPE ' || cols.schema_name || '.' || cols.obj_name || E' AS (\n    ' ||
    pg_catalog.array_to_string (ARRAY( 
        SELECT cols.column_name || ' ' || cols.data_type AS col_num_typ
        FROM cols
        WHERE cols.obj_name='my_user_data_type'
        ORDER BY cols.schema_name,
                cols.obj_name,
                cols.ordinal_position ), E',\n    '
        ) || E'\n);'
    AS cre_typ
    FROM cols
    WHERE cols.obj_name='my_user_data_type'
    LIMIT 1
    

    并使用此命令在 psql 下运行它,以便只有 SQL 代码:

    \t\a\g\a\t

    【讨论】:

      【解决方案2】:

      检查一下:

      select enum_range(null::my_type)
      

      我认为这是一个更简单的解决方案:)。

      【讨论】:

      • 我喜欢这个简单的。无论如何,评分最高的作品......但这个也是。 :)
      • 我喜欢这个。 \d 语法在 dbeaver 或 pgadmin 中不起作用,但可移植的纯 SQL
      • 在 PostgreSQL 8.3.11 中工作
      • 如果我的表被称为users 并且列status 并且枚举类型是enum_user_status,我应该输入什么而不是null:my_type?我尝试了所有我能想到的组合,但一无所获。
      • @exebook 我来晚了,但我使用了null::enum_user_status(显然我使用了我的枚举名称而不是enum_user_status)。不涉及使用枚举的表/列。
      【解决方案3】:

      如果您只需要全名(类型名称和架构)和所有enum 标签的排序列表,则此查询可以:

      SELECT n.nspname AS "schema", t.typname
           , string_agg(e.enumlabel, '|' ORDER BY e.enumsortorder) AS enum_labels
      FROM   pg_catalog.pg_type t 
      JOIN   pg_catalog.pg_namespace n ON n.oid = t.typnamespace 
      JOIN   pg_catalog.pg_enum e ON t.oid = e.enumtypid  
      WHERE  t.typname = 'my_enum_type'
      GROUP  BY 1,2;
      

      返回:

       schema | typname      | enum_labels
      --------+--------------+-------------
       public | my_enum_type | foo|bar
      

      string_agg() 需要 Postgres 9.0 或更高版本,旧版本替换为 array_agg()


      要获取 SQL CREATE 语句,您可以使用 pg_dump 并查看转储文件。

      或者,更实际地,使用pgAdmin,它会为数据库中的任何对象显示反向工程 SQL 创建脚本。在object browser 中选择它,它的创建脚本会显示在SQL pane 中。甚至可以选择自动将脚本复制到SQL editor 新打开的窗口中,您可以在其中编辑和执行它。

      【讨论】:

      • 请注意,您需要默认启用pgAdmin中的查看类型:文件→选项→浏览器并检查Types
      • 实际上从 1.18.1 版本开始,您可以在文件 -> 选项 -> 显示中找到该选项。
      【解决方案4】:

      这是您所追求的 \dT,但它并没有将其作为“CREATE”语句给出。您将 \dD 用于域。

      \dT+ action.action_status
                                List of data types
       Schema |         Name         | Internal name | Size | Elements | Description 
      --------+----------------------+---------------+------+----------+-------------
       action | action.action_status | action_status | 4    | pending +| 
              |                      |               |      | live    +| 
              |                      |               |      | done    +| 
              |                      |               |      | notdone  | 
      (1 row)
      

      【讨论】:

      • 我不明白“您将 \dD 用于域”的相关性。
      • 域和类型是不同的东西。您将 \dD 用于域,将 \dT 用于类型。
      • 好的,我明白了。 “域本质上是一种具有可选约束(对允许的值集的限制)的数据类型。”
      • 我花了一点时间才意识到我真正想要的是\dT+ my_enum;
      【解决方案5】:
      SELECT t.typname
      FROM pg_class c JOIN pg_attribute a ON c.oid = a.attrelid JOIN pg_type t ON a.atttypid = t.oid
      WHERE c.relname = 'your_type';
      

      棘手的部分是,简单地从这些视图中选择 * 不会在结果中获得 OID。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        相关资源
        最近更新 更多