Oracle má vestavěnou funkci pro získání obsahu tabulky jako XML:
create table t42(id number, str varchar2(10));
insert into t42 values (1, 'AA');
insert into t42 values (2, 'BB');
select dbms_xmlgen.getxmltype('select * from t42')
from dual;
DBMS_XMLGEN.GETXMLTYPE('SELECT*FROMT42')
----------------------------------------
<ROWSET>
<ROW>
<ID>1</ID>
<STR>AA</STR>
</ROW>
<ROW>
<ID>2</ID>
<STR>BB</STR>
</ROW>
</ROWSET>
Kolem toho můžete přidat své vlastní značky; lze provést jako dotaz, ale protože chcete uloženou proceduru:
create or replace function table_to_xml(table_name in varchar2) return xmltype as
xml xmltype;
begin
select xmlelement("XML",
xmlelement(evalname(table_name),
dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
into xml
from dual;
return xml;
end table_to_xml;
/
select table_to_xml('T42') from dual;
TABLE_TO_XML('T42')
----------------------------------------
<XML><T42><ROWSET>
<ROW>
<ID>1</ID>
<STR>AA</STR>
</ROW>
<ROW>
<ID>2</ID>
<STR>BB</STR>
</ROW>
</ROWSET>
</T42></XML>
Takže to má strukturu, kterou chcete (no, myslím, ale viz níže), ale má ROWSET
a ROW
místo RECORDS
a RECORD
. To může nezáleží, záleží na tom, zda stále vyvíjíte formát pro toto rozhraní. Pokud na tom záleží, můžete použít další krok pro přejmenování těchto uzlů
, nebo - což je užitečnější - použijte dbms_xmlgen
procedury setrowsettag
a setrowtag
, což je ve vašem postupu jednoduché (a ukázáno níže).
Předpokládám, že to, co jste ukázali jako <TABLENAME></TABLENAME>
byla chyba a chcete záznamy v této značce. Pokud ne a z nějakého důvodu to opravdu chcete, změňte dotaz ve funkci na:
select xmlelement("XML",
xmlconcat(xmlelement(evalname(table_name), null),
dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
into xml
from dual;
To pak můžete zapsat do souboru jakýmkoli způsobem, který byste normálně dělali; pokud voláte z SQL*Plus atd., můžete vybrat a zařadit, nebo pokud nechcete, aby se to vrátilo vůbec, můžete přidat UTL_FILE
direktiva pro zápis souboru z procedury, ale to by muselo být do objektu adresáře na serveru DB, což nemusí být vhodné.
Většinou pro můj vlastní prospěch, protože s XML toho moc nedělám:
create or replace procedure table_to_xml_file(table_name in varchar2) as
ctx dbms_xmlgen.ctxhandle;
clb clob;
file utl_file.file_type;
buffer varchar2(32767);
position pls_integer := 1;
chars pls_integer := 32767;
begin
ctx := dbms_xmlgen.newcontext('select * from "' || table_name || '"');
dbms_xmlgen.setrowsettag(ctx, 'RECORDS');
dbms_xmlgen.setrowtag(ctx, 'RECORD');
select xmlserialize(document
xmlelement("XML",
xmlelement(evalname(table_name),
dbms_xmlgen.getxmltype(ctx)))
indent size = 2)
into clb
from dual;
dbms_xmlgen.closecontext(ctx);
file := utl_file.fopen('<directory>', table_name || '.xml', 'w', 32767);
while position < dbms_lob.getlength(clb) loop
dbms_lob.read(clb, chars, position, buffer);
utl_file.put(file, buffer);
utl_file.fflush(file);
position := position + chars;
end loop;
utl_file.fclose(file);
end table_to_xml_file;
/
Při spuštění pomocí exec table_to_xml_file('T42')
, vytvoří se soubor s názvem T42.xml
v adresáři serveru, na který ukazuje <directory>
adresářový objekt, který obsahuje:
<XML>
<T42>
<RECORDS>
<RECORD>
<ID>1</ID>
<STR>AA</STR>
</RECORD>
<RECORD>
<ID>2</ID>
<STR>BB</STR>
</RECORD>
</RECORDS>
</T42>
</XML>
Mimochodem, dal jsem název tabulky do uvozovek ve výběru uvnitř dbms_xmlgen.getxmltype
volání. To je pro splnění požadavku 'případ by měl být stejný jako v databázi' pro název tabulky; musí být předán postupu ve správném případě, jinak dojde k chybě. Je to jednodušší, než se nějak pokoušet opravit případ v rámci procedury, což by bylo nešikovné nebo nemožné, pokud byste kromě případu měli dvě tabulky se stejným názvem. Názvy sloupců budou stejně ve správných velikostech.