Jak mohu napsat SQL pro čtení XML souboru do PostgreSQL XML
hodnoty?
PostgreSQL má nativní datový typ XML s funkcí XMLPARSE
pro analýzu textového řetězce na tento typ. Má také způsoby, jak číst data ze souborového systému; mimo jiné prohlášení COPY
.
Ale nevidím způsob, jak psát nativní příkazy SQL PostgreSQL pro čtení obsahu ze záznamu souborového systému a použít jej k naplnění hodnoty XML
. Jak to mohu udělat?
Funkce pg_read_binary_file
to dokáže.
Má omezení: nové v PostgreSQL 9.1 nebo vyšší; musí to být relace vlastněná superuživatelem databáze; musí číst soubor v adresáři databáze nebo níže. Ty jsou v mém případě použití přijatelné.
Při vytváření nativní hodnoty XML
ze souboru tedy bude fungovat následující:
-- PostgreSQL 9.1 or later.
SELECT
XMLPARSE(DOCUMENT convert_from(
pg_read_binary_file('foo.xml'), 'UTF8'));
V PostgreSQL 8.3 - 9.0 lze použít funkci pg_read_file
, s dalším omezením, že nemůžete specifikovat kódování specifické pro soubor (v aktuálním souboru jej přečte jako text kódování relace).
-- PostgreSQL earlier than 9.1.
SELECT
XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
Podobně jako this odpověď na předchozí otázku, a pokud nechcete omezení pg_read_file()
(zkrátka: pg_read_file
neumí číst soubory mimo adresář databáze a čte text v kódování znaků aktuální relace).
Tato funkce funguje pro jakoukoli cestu, ale musí být vytvořena jako superuživatel:
create or replace function stack.bytea_import(p_path text, p_result out bytea)
language plpgsql as $$
declare
l_oid oid;
begin
select lo_import(p_path) into l_oid;
select lo_get(l_oid) INTO p_result;
perform lo_unlink(l_oid);
end;$$;
lo_get
byl představen v 9.4, takže pro starší verze byste potřebovali:
create or replace function stack.bytea_import(p_path text, p_result out bytea)
language plpgsql as $$
declare
l_oid oid;
r record;
begin
p_result := '';
select lo_import(p_path) into l_oid;
for r in ( select data
from pg_largeobject
where loid = l_oid
order by pageno ) loop
p_result = p_result || r.data;
end loop;
perform lo_unlink(l_oid);
end;$$;
pak:
select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;
Zveřejnil jsem kompletní implementaci toho, co požadujete v nedávná odpověď na SO .
Klíčovými funkcemi jsou funkce xpath()
, pg_read_file()
, ovládání pole, funkce plpgsql, ..