PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

jak mogę utworzyć nowy plik XML z istniejącej bazy danych w bazie danych PostgreSQL za pomocą java?

Mam działającą implementację, w której robię wszystko wewnątrz PostgreSQL bez dodatkowych bibliotek.

Pomocnicza funkcja analizowania

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;

Obsługa wielu wartości

Powyższa implementacja nie obsługuje wielu atrybutów na jednym xpath. Oto przeładowana wersja f_xml_extract_val() za to. Za pomocą trzeciego parametru możesz wybrać one (pierwszy), all lub dist (różne) wartości. Wiele wartości jest agregowanych w ciąg znaków oddzielonych przecinkami.

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'

Zadzwoń:

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

Część główna

Nazwa tabeli docelowej:tbl; sztywny. klucz: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;

Ważne uwagi

  • Ta implementacja sprawdza klucz podstawowy, jeśli wstawiony wiersz już istnieje, i aktualizacje w tym przypadku. Wstawiane są tylko nowe wiersze.

  • Używam tymczasowej tabeli pomostowej, aby przyspieszyć procedurę.

  • Testowane z Postgresem 8.4 , 9.0 i 9.1 .

  • XML musi być dobrze sformułowany.

  • pg_read_file() ma ograniczenia. Instrukcja:

    Korzystanie z tych funkcji jest ograniczone do superużytkowników.

    Oraz:

    Tylko pliki w katalogu klastra bazy danych i log_directory można uzyskać dostęp.

Musisz więc umieścić tam swój plik źródłowy - lub utworzyć dowiązanie symboliczne do twojego aktualnego pliku/katalogu.

Lub możesz dostarczyć plik przez Javę w swoim przypadku (zrobiłem to wszystko w Postgresie).

Lub możesz zaimportować dane do 1 kolumny w 1 wierszu tabeli tymczasowej i stamtąd je pobrać.

Lub możesz użyć lo_import jak pokazano w tej powiązanej odpowiedzi na dba.SE.

  • SQL do odczytu XML z pliku do bazy danych PostgreSQL

Ten wpis na blogu autorstwa Scotta Baileya pomógł mi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. dołącz do dwóch różnych tabel i usuń zduplikowane wpisy

  2. Próbka tabel i inne metody uzyskiwania losowych krotek

  3. Jak wdrożyć Teamcity z PostgreSQL w celu zapewnienia wysokiej dostępności

  4. W mojej bazie danych PostgreSQL brakuje miejsca na dysku

  5. Dlaczego dostęp do tablicy PostgreSQL jest znacznie szybszy w C niż w PL/pgSQL?