sql >> Databasteknik >  >> RDS >> Oracle

generera XML från oracle-tabeller

Oracle har en inbyggd funktion för att få innehållet i en tabell som 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>

Du kan lägga till dina egna taggar runt det; kan göras som en fråga men eftersom du vill ha en lagrad procedur:

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>

Så det här har den struktur du vill ha (ja, tror jag, men se nedan), men har ROWSET och RAD istället för RECORDS och RECORD . Det kan spelar ingen roll, det beror på om du fortfarande utvecklar formatet för det här gränssnittet. Om det spelar någon roll kan du använda ytterligare ett steg för att byta namn på dessa noder , eller - mer användbart - använd dbms_xmlgen procedurer setrowsettag och setrowtag , vilket är enkelt i din procedur (och visas nedan).

Jag antar att det du visade som var ett misstag, och du vill ha posterna i den taggen. Om inte, och du verkligen vill det av någon anledning, ändra frågan i funktionen till:

  select xmlelement("XML",
      xmlconcat(xmlelement(evalname(table_name), null),
      dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
  into xml
  from dual;

Du kan sedan skriva ut det till en fil som du normalt skulle göra; om du ringer från SQL*Plus etc. kan du välja och spoola, eller om du inte vill att det returneras alls kan du lägga till UTL_FILE direktiv för att skriva filen från proceduren, men det måste vara till ett katalogobjekt på DB-servern, vilket kanske inte är bekvämt.

Mest för min egen skull då jag inte gör så mycket med 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;
/

När den körs med exec table_to_xml_file('T42') , producerar detta en fil som heter T42.xml i serverkatalogen som pekas på av katalogobjekt, som innehåller:

<XML>
  <T42>
    <RECORDS>
      <RECORD>
        <ID>1</ID>
        <STR>AA</STR>
      </RECORD>
      <RECORD>
        <ID>2</ID>
        <STR>BB</STR>
      </RECORD>
    </RECORDS>
  </T42>
</XML>

Jag har för övrigt satt dubbla citattecken runt tabellnamnet i select inuti dbms_xmlgen.getxmltype ringa upp. Det är för att uppfylla kravet 'case should be same as in database' för tabellnamnet; det måste skickas till proceduren i rätt fall annars kommer det att fel. Det är enklare än att försöka korrigera fallet inom proceduren på något sätt, vilket skulle vara besvärligt eller omöjligt om du hade två tabeller med samma namn förutom fallet. Kolumnnamnen kommer ändå att ha rätt versaler.




  1. Uppdaterar redan markerade kryssrutor i PHP

  2. Riktig flyktsträng och PDO

  3. Behöver beräkna med avrundad tid eller datum siffra i sql server

  4. Hur man bara lagrar tid; inte datum och tid?