Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

tạo XML từ các bảng tiên tri

Oracle có một hàm tích hợp để lấy nội dung của bảng dưới dạng 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>

Bạn có thể thêm các thẻ của riêng bạn xung quanh đó; có thể được thực hiện như một truy vấn nhưng vì bạn muốn một thủ tục được lưu trữ:

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>

Vì vậy, điều này có cấu trúc bạn muốn (tôi nghĩ vậy, nhưng hãy xem bên dưới), nhưng có ROWSETROW thay vì RECORDSRECORD . Điều đó có thể không quan trọng, nó phụ thuộc vào việc bạn có đang phát triển định dạng cho giao diện này hay không. Nếu điều đó không thành vấn đề thì bạn có thể áp dụng một bước tiếp theo để đổi tên các nút đó hoặc - hữu ích hơn - sử dụng dbms_xmlgen thủ tục setrowsettagsetrowtag , đơn giản trong thủ tục của bạn (và được trình bày bên dưới).

Tôi giả định những gì bạn đã hiển thị là <TABLENAME></TABLENAME> là một sai lầm và bạn muốn các bản ghi trong thẻ đó. Nếu không, và bạn thực sự muốn điều đó vì lý do nào đó, hãy thay đổi truy vấn trong hàm thành:

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

Sau đó, bạn có thể ghi điều đó ra tệp theo bất kỳ cách nào bạn thường làm; nếu bạn đang gọi từ SQL * Plus, v.v., bạn có thể chọn và cuộn hoặc nếu bạn không muốn nó được trả lại, bạn có thể thêm UTL_FILE chỉ thị để ghi tệp từ bên trong thủ tục, nhưng điều đó sẽ phải đến một đối tượng thư mục trên máy chủ DB, điều này có thể không thuận tiện.

Chủ yếu là vì lợi ích của riêng tôi vì tôi không làm nhiều với 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;
/

Khi chạy với exec table_to_xml_file('T42') , điều này tạo ra một tệp có tên là T42.xml trong thư mục máy chủ được trỏ đến bởi <directory> đối tượng thư mục, chứa:

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

Tình cờ, tôi đã đặt dấu ngoặc kép xung quanh tên bảng trong vùng chọn bên trong dbms_xmlgen.getxmltype cuộc gọi. Điều đó để đáp ứng yêu cầu 'trường hợp phải giống như trong cơ sở dữ liệu' cho tên bảng; nó phải được chuyển cho thủ tục trong trường hợp chính xác, nếu không nó sẽ bị lỗi. Điều đó đơn giản hơn là cố gắng sửa trường hợp trong quy trình bằng cách nào đó, điều này sẽ rất khó xử hoặc không thể nếu bạn có hai bảng có cùng tên ngoài trường hợp. Dù sao thì tên các cột cũng sẽ ở trong trường hợp chính xác.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Số nhận dạng ORA-00972 là tên cột bí danh quá dài

  2. Tải dữ liệu vào bảng được phân vùng lớn

  3. Cách kết nối với Kết nối cơ sở dữ liệu Oracle từ .Net Core

  4. Cách giới hạn các hàng trong đó SUM của một cột bằng với giá trị nhất định trong Oracle

  5. Tại sao tôi nhận được lỗi này? Không thể chèn null vào 'VALUE.VALUE_TX'