Oracle ma wbudowaną funkcję pobierania zawartości tabeli 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>
Możesz dodać własne znaczniki wokół tego; można wykonać jako zapytanie, ale ponieważ chcesz procedurę składowaną:
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>
Więc to ma strukturę, którą chcesz (dobrze, myślę, ale patrz poniżej), ale ma ROWSET
i ROW
zamiast REKORDÓW
i NAGRAJ
. To może nie ma znaczenia, zależy to od tego, czy nadal rozwijasz format tego interfejsu. Jeśli ma to znaczenie, możesz zastosować kolejny krok w celu zmiany nazw tych węzłów
lub – bardziej pomocnie – użyj dbms_xmlgen
procedury setrowsettag
i setrowtag
, który jest prosty w twojej procedurze (i zademonstrowany poniżej).
Zakładam, że pokazałeś jako
select xmlelement("XML",
xmlconcat(xmlelement(evalname(table_name), null),
dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
into xml
from dual;
Następnie możesz zapisać to do pliku w normalny sposób; jeśli dzwonisz z SQL*Plus itp. możesz wybrać i spoolować, lub jeśli nie chcesz, aby w ogóle zwracano, możesz dodać UTL_FILE
dyrektywy, aby zapisać plik z wnętrza procedury, ale to musiałoby być do obiektu katalogu na serwerze DB, co może nie być wygodne.
Głównie dla własnej korzyści, ponieważ niewiele robię z XML:
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;
/
Po uruchomieniu z exec table_to_xml_file('T42')
, tworzy to plik o nazwie T42.xml
w katalogu serwera wskazywanym przez
<XML>
<T42>
<RECORDS>
<RECORD>
<ID>1</ID>
<STR>AA</STR>
</RECORD>
<RECORD>
<ID>2</ID>
<STR>BB</STR>
</RECORD>
</RECORDS>
</T42>
</XML>
Nawiasem mówiąc, umieściłem podwójne cudzysłowy wokół nazwy tabeli w zaznaczeniu wewnątrz dbms_xmlgen.getxmltype
połączenie. Ma to na celu spełnienie wymogu „sprawa powinna być taka sama jak w bazie danych” dla nazwy tabeli; musi zostać przekazany do procedury we właściwym przypadku, w przeciwnym razie wystąpi błąd. To prostsze niż próba poprawienia wielkości liter w ramach procedury, co byłoby niezręczne lub niemożliwe, gdybyś miał dwie tabele o tej samej nazwie oprócz wielkości liter. Nazwy kolumn i tak będą miały prawidłową wielkość liter.