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ó ROWSET
và ROW
thay vì RECORDS
và RECORD
. Đ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 setrowsettag
và setrowtag
, đơ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.