PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

как мога да създам нов XML файл от съществуваща база данни в PostgreSQL база данни с помощта на java

Имам работеща реализация, в която правя всичко вътре в 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() за това. С 3-тия параметър можете да изберете one (първото), all или dist (различни) стойности. Няколко стойности се обобщават в низ, разделен със запетая.

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.4 , 9.0 и 9.1 .

  • XML трябва да е добре оформен.

  • pg_read_file() има ограничения към него. Ръководството:

    Използването на тези функции е ограничено до суперпотребители.

    И:

    Само файлове в клъстерната директория на базата данни и log_directory може да бъде достъпен.

Така че трябва да поставите своя изходен файл там - или да създадете символна връзка към действителния си файл/директория.

Или можете да предоставите файла чрез Java във вашия случай (направих всичко в Postgres).

Или можете да импортирате данните в 1 колона от 1 ред на временна таблица и да ги вземете от там.

Или можете да използвате lo_import както е показано в този свързан отговор на dba.SE.

  • SQL за четене на XML от файл в PostgreSQL база данни

Тази публикация в блога на Скот Бейли ми помогна.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres:как закръгляте времевата марка нагоре или надолу до най-близката минута?

  2. Запазете изхода от sql функция в csv файл (COPY) с динамично име на файл

  3. Изпълнявайте отложен тригер само веднъж на ред в PostgreSQL

  4. Транзакциите не работят за моята MySQL DB

  5. ГИС:PostGIS/PostgreSQL срещу MySql срещу SQL Server?