sql >> Databáze >  >> RDS >> PostgreSQL

jak mohu vytvořit nový soubor XML z existující databáze v databázi PostgreSQL pomocí javy

Mám funkční implementaci, kde dělám vše uvnitř PostgreSQL bez dalších knihoven.

Pomocná funkce analýzy

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;

Ovládejte více hodnoty

Výše uvedená implementace nezpracovává více atributů na jedné xpath. Zde je přetížená verze f_xml_extract_val() pro to. Pomocí 3. parametru můžete vybrat one (první), all nebo dist (výrazné) hodnoty. Více hodnot je agregováno do řetězce odděleného čárkami.

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'

Volejte:

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

Hlavní část

Název cílové tabulky:tbl; prim. klíč: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;

Důležité poznámky

  • Tato implementace kontroluje primární klíč, zda vložený řádek již existuje, a aktualizuje se v tomto případě. Vkládají se pouze nové řádky.

  • Pro urychlení postupu používám dočasnou pracovní tabulku.

  • Testováno pomocí Postgres 8.4 , 9.0 a 9.1 .

  • XML musí být ve správném formátu.

  • pg_read_file() má na to omezení. Manuál:

    Použití těchto funkcí je omezeno na superuživatele.

    A:

    Pouze soubory v adresáři databázového clusteru a log_directory lze získat přístup.

Takže tam musíte vložit svůj zdrojový soubor – nebo vytvořit symbolický odkaz na váš aktuální soubor/adresář.

Nebo ve vašem případě můžete soubor poskytnout prostřednictvím Javy (udělal jsem to všechno v Postgresu).

Nebo můžete importovat data do 1 sloupce z 1 řádku dočasné tabulky a převzít je odtud.

Nebo můžete použít lo_import jak je ukázáno v této související odpovědi na dba.SE.

  • SQL pro čtení XML ze souboru do databáze PostgreSQL

Tento blogový příspěvek od Scotta Baileyho mi pomohl.



  1. Jak získat odlišné záznamy z tabulky v SQL Server - SQL Server / TSQL Tutorial 112

  2. SQLSTATE[42000]:Chyba syntaxe nebo porušení přístupu:1064 Máte chybu v syntaxi SQL — PHP — PDO

  3. Západka FGCB_ADD_REMOVE

  4. Rails:Žádný fond připojení pro ActiveRecord::Base