如何使用 java 从 PostgreSQL 数据库中的现有数据库创建新的 XML 文件 [关闭]

Posted

技术标签:

【中文标题】如何使用 java 从 PostgreSQL 数据库中的现有数据库创建新的 XML 文件 [关闭]【英文标题】:how can I create new XML file from existing database in PostgreSQL database using java [closed] 【发布时间】:2011-11-21 10:22:31 【问题描述】:

将 XML 数据(我从网页获取)插入 PostgreSQL 数据库的最佳方法是什么? 我正在使用 Java,需要一些帮助才能找到将这些数据读入数据库的好方法。

【问题讨论】:

当您说xml数据到数据库时,您的意思是要插入完整的xml(作为字符串/文本)或解析字段并插入每个字段? 只是将xml文件添加到数据库中,或者从中解析值并保存到特定的表中? 这是数据 sedlabanki.is/?PageID=289 是的,我有一张表,该数据应该进入该表,该表与每个 具有相同的列。 【参考方案1】:

我有一个有效的实现,我在 PostgreSQL 中执行所有操作,无需额外的库。

辅助解析功能

CREATE OR REPLACE FUNCTION f_xml_extract_val(text, xml)
  RETURNS text AS
$func$
SELECT CASE
        WHEN $1 ~ '@[[:alnum:]_]+$' THEN
           (xpath($1, $2))[1]
        WHEN $1 ~* '/text()$' THEN
           (xpath($1, $2))[1]
        WHEN $1 LIKE '%/' THEN
           (xpath($1 || 'text()', $2))[1]
        ELSE
           (xpath($1 || '/text()', $2))[1]
       END;
$func$  LANGUAGE sql IMMUTABLE;

处理多个

上述实现不会在一个 xpath 处处理多个属性。这是f_xml_extract_val() 的overloaded 版本。使用第三个参数,您可以选择 one(第一个)、alldist(不同)值。多个值聚合为一个逗号分隔的字符串。

CREATE OR REPLACE FUNCTION f_xml_extract_val(_path text, _node xml, _mode text)
  RETURNS text AS
$func$
DECLARE
   _xpath text := CASE
                   WHEN $1 ~~ '%/'              THEN $1 || 'text()'
                   WHEN lower($1) ~~ '%/text()' THEN $1
                   WHEN $1 ~ '@\w+$'            THEN $1
                   ELSE                              $1 || '/text()'
                  END;
BEGIN
   -- fetch one, all or distinct values
   CASE $3
       WHEN 'one'  THEN RETURN (xpath(_xpath, $2))[1]::text;
       WHEN 'all'  THEN RETURN array_to_string(xpath(_xpath, $2), ', ');
       WHEN 'dist' THEN RETURN array_to_string(ARRAY(
            SELECT DISTINCT unnest(xpath(_xpath, $2))::text ORDER BY 1), ', ');
       ELSE RAISE EXCEPTION
          'Invalid $3: >>%<<', $3;
   END CASE;
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_xml_extract_val(text, xml, text) IS '
Extract element of an xpath from XML document
Overloaded function to f_xml_extract_val(..)
$3 .. mode is one of: one | all | dist'

呼叫:

SELECT f_xml_extract_val('//city', x, 'dist');

主要部分

目标表名称:tbl;首要的。键:id

CREATE OR REPLACE FUNCTION f_sync_from_xml()
  RETURNS boolean AS
$func$
DECLARE
   datafile text := 'path/to/my_file.xml';  -- only relative path in db dir
   myxml    xml  := pg_read_file(datafile, 0, 100000000); -- arbitrary 100 MB
BEGIN
   -- demonstrating 4 variants of how to fetch values for educational purposes
   CREATE TEMP TABLE tmp ON COMMIT DROP AS
   SELECT (xpath('//some_id/text()', x))[1]::text AS id   -- id is unique  
        , f_xml_extract_val('//col1', x)          AS col1 -- one value
        , f_xml_extract_val('//col2/', x, 'all')  AS col2 -- all values incl. dupes
        , f_xml_extract_val('//col3/', x, 'dist') AS col3 -- distinct values
   FROM   unnest(xpath('/xml/path/to/datum', myxml)) x;

   -- 1.) DELETE?

   -- 2.) UPDATE
   UPDATE tbl t
   SET   (  col_1,   col2,   col3) =
         (i.col_1, i.col2, i.col3)
   FROM   tmp i
   WHERE  t.id = i.id
   AND   (t.col_1, t.col2, t.col3) IS DISTINCT FROM
         (i.col_1, i.col2, i.col3);

   -- 3.) INSERT NEW
   INSERT INTO tbl
   SELECT i.*
   FROM   tmp i
   WHERE  NOT EXISTS (SELECT 1 FROM tbl WHERE id = i.id);
END
$func$  LANGUAGE plpgsql;

重要提示

如果插入的行已经存在并且在这种情况下更新,此实现会检查主键。只插入新行。

我使用临时登台表来加快过程。

使用 Postgres 8.49.09.1 测试。

XML 必须格式正确。

pg_read_file() 对此有限制。 The manual:

这些功能的使用仅限于超级用户。

还有:

只能访问数据库集群目录和log_directory中的文件。

所以你必须把你的源文件放在那里 - 或者创建一个指向你的实际文件/目录的符号链接。

或者您可以在您的情况下通过 Java 提供文件(我在 Postgres 中完成了所有操作)。

或者您可以将数据导入到临时表的 1 行的 1 列中,然后从那里取出。

或者你可以使用lo_import,就像在这个related answer on dba.SE中演示的那样。

SQL to read XML from file into PostgreSQL database

这个博客post by Scott Bailey帮助了我。

【讨论】:

如果xml行包含保留字符如“'”或“&”我必须做什么??【参考方案2】:

Postgres 有(感谢 Daniel Lyons 指出)native XML support,您可以使用它来存储您的表格。但是,如果您想手动分解您的 XML 数据,那么在数据库中表示 XML 数据有不同的可能性。第一个问题应该是,如果您想要一个非常通用的解决方案,它将能够存储任何 XML 文档或特定于您的域的文档(即只允许特定结构的 XML 文档)。取决于此,您将拥有一个非常灵活、通用的表示,但更难查询(所需的 SQL 将非常复杂)。如果您有更具体的方法,查询会更简单,但是每次您想要存储另一种类型的文档或向现有文档添加字段时,您都需要创建新表或向现有表添加新属性;因此更改模式将更加困难(这是 XML 的主要优势之一)。 This presentation 应该会给你一些想法,有哪些不同的可能性。

另外,您可能会考虑切换到一些支持 Xquery 的数据库,例如 DB2。使用 XQuery(一种旨在处理 XML 的语言)进行本机查询的能力将大大简化事情。

更新:根据您的评论,您的 XML 数据(即you linked to)是完全相关的。可以1:1映射到下表:

CREATE TABLE mynt (
    ID          SERIAL     ,
    myntnafn    CHAR(3)    ,
    myntheiti   Varchar(255) ,
    kaupgengi   Decimal(15,2) ,
    midgengi    Decimal(15,2) ,
    solugengi   Decimal(15,2) ,
    dagsetning  TimeStamp      
)

因此,任何mynt 标记都将是表中的一条记录,并且相应的子标记是属性。我从您的数据中收集的数据类型,它们可能是错误的。主要问题是,IMO,没有自然主键,所以我添加了一个自动生成的主键。

【讨论】:

PostgreSQL has had native XML support since version 8.2. 呃,对不起,假设它没有给出问题。 @Daniel:我现在更新它以反映 PostgreSQL 具有 XML 的事实。然而,从我收集到的信息来看,DB2 仍然具有 XQuery 的优势。 我将使用 postgres,但我在上面的评论中链接的 xml 数据是我将使用的唯一类型的数据。我需要在我的表中插入的所有 XML 都将像这个 xml,所以我永远不会添加新属性或类似的东西。我要多用谷歌搜索一些东西,但如果你知道我可以用什么来做这件事,请分享:)。 (对不起,如果我的英语很差,不是我最强的一面)。 @MaxvonHippel 他们今天似乎正在工作,但无论如何,我无法编辑四年前评论中的链接,所以你最好只留下更正的链接。跨度> 【参考方案3】:

PostgreSQL 有一个XML datatype。有很多XML specific functions可以用来查询和修改数据,比如用xpath。

在 Java 方面,您可以假装您只是在处理字符串,但要知道数据在输出时格式正确,并且不会让您存储格式不正确的数据。

【讨论】:

以上是关于如何使用 java 从 PostgreSQL 数据库中的现有数据库创建新的 XML 文件 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Java连接PostgreSQL数据库

Java连接PostgreSQL数据库

Java连接PostgreSQL数据库

如何从PostgreSQL json中提取数组

使用 jooq/postgresql 从 json 中提取键/值对 - java

如何调用从 Java 代码返回 TABLE 类型的 postgresql 函数?