【问题标题】:How to get array base type in postgres via jdbc如何通过 jdbc 在 postgres 中获取数组基类型
【发布时间】:2013-05-13 05:11:24
【问题描述】:

如何通过 Java 获取 Postgres 中数组列的基本类型/维度?

我有一个包含 int[][]text[] 等数组的表。

当我从 JDBC 遍历元数据时,我只能得到java.sql.Array 的类型。 即使在 information_schema.columns 中,它也仅存储为 ARRAY。

我如何知道基本类型及其维度?

我现在正在开发用于转储表信息的工具。

【问题讨论】:

    标签: java arrays postgresql jdbc types


    【解决方案1】:

    除了@Joe already cleared up之外,还可以使用pg_typof()从PostgreSQL获取类型信息。

    在这个例子中给定一个二维整数数组:

    SELECT pg_typeof(a)::text AS type
          ,(SELECT typname FROM pg_type WHERE oid = pg_typeof(a)) AS base_type
          ,array_dims(a) AS dims
    FROM   (SELECT '{{11,12,13},{21,22,23}}'::int[]) x(a);
    
       type    | base_type |    dims
    -----------+-----------+------------
     integer[] | _int4     | [1:2][1:3]
    

    请注意,每个值的数组维度 (dims) 可能不同。 Postgres 目前不强制使用维度(直到并包括 v9.3)。
    As documented in the manualpg_attribute.attndims 在这里的用途有限:

    维数,如果列是数组类型;否则为 0。 (目前,数组的维数没有强制要求,所以 任何非零值实际上意味着“它是一个数组”。)

    【讨论】:

    • 意识到你最终是真的,维度不可靠:)
    【解决方案2】:

    对于数组基类型,DatabaseMetaData.getColumns() 返回一个包含列元数据的ResultSet。返回的列之一是TYPE_NAME。这似乎包含数组基本类型的名称,前缀为下划线。例如,_int4_textpg_type 中有一些关于类型的附加信息可能会有所帮助。

    对于维度,它们似乎不太可能出现在元数据中。来自documentation

    但是,当前实现忽略任何提供的数组大小限制,即行为与未指定长度的数组相同。

    当前的实现也不强制声明的维数。无论大小或维数如何,特定元素类型的数组都被认为是同一类型。因此,在 CREATE TABLE 中声明数组大小或维数只是文档;它不会影响运行时行为。

    array_dims 函数将返回数组值的当前维度。但由于表中的每一行都可能不同,我怀疑这会对您有所帮助。

    更新:看起来维度在元数据中可用。见@a_horse_with_no_name's answer

    【讨论】:

    • 您的更新有问题,@a_horse 在这件事上也是如此。查看我留下的评论。
    • @ErwinBrandstetter 虽然我同意它没有被强制执行,但信息似乎仍然存在。我刚刚在 9.1.9 上测试了最多 1 到 3 个维度,attndims 是正确的。
    • 不可能是“正确的”,因为没有“正确的”。无论您如何声明该列,所讨论的列都可以包含任意维度的数组。你不必相信我,试试看。 attndims 中超出0 / > 0 的信息仅适用于intent 的文档。不保证任何关于实际值的内容。
    • @ErwinBrandstetter 我明白你在说什么,我相信你。我要说的是用于声明列的维数在元数据中。我不是说它是由数据库强制执行的,或者您不能或多或少地投入其中。
    • 以任何方式依赖这些信息都是不明智的。不应指示人们使用它。
    【解决方案3】:

    您可以直接查询pg_attributes

    select att.attname, 
           att.attndims, 
           pg_catalog.format_type(atttypid, NULL) as display_type 
    from pg_attribute att 
      join pg_class tbl on tbl.oid = att.attrelid  
      join pg_namespace ns on tbl.relnamespace = ns.oid  
    where tbl.relname = 'your_table_name'  
      and ns.nspname = 'table_schema'
    

    SQLFiddle 示例:http://sqlfiddle.com/#!12/50301/1

    请注意,format_type() 实际上会返回 integer[],即使该列定义为 int[][],但 attndims 列将包含您想要的信息。

    【讨论】:

    • attndims 打算用于此目的,但目前尚未实施或强制执行,如the manual informsNumber of dimensions, if the column is an array type; otherwise 0. (Presently, the number of dimensions of an array is not enforced, so any nonzero value effectively means "it's an array".)
    • @ErwinBrandstetter:问题是“如何获取数组列的维度”,这正是attndims 所做的。将数据放入该列时未强制执行这一事实与该问题无关(至少目前还没有......)
    • 谢谢 :) 是的,我直到现在才意识到数组维度没有被强制执行。
    猜你喜欢
    • 1970-01-01
    • 2012-01-08
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多