我将从我想要的输出开始:
<?xml version="1.0"?>
<Accounts>
<Account>
<variable1>variable1</variable1>
<variable2>variable2</variable2>
<variable3>variable3</variable3>
<variable4>variable4</variable4>
<variable5>variable5</variable5>
<variable6>variable6</variable6>
<Table>
<Row>
<Column1>row1col1</Column1>
<Column2>row1col2</Column2>
<Column3>row1col3</Column3>
</Row>
<Row>
<Column1>row2col1</Column1>
<Column2>row2col2</Column2>
<Column3>row2col3</Column3>
</Row>
<Row>
<Column1>row3col1</Column1>
<Column2>row3col2</Column2>
<Column3>row3col3</Column3>
</Row>
</Table>
</Account>
...
</Accounts>
这需要来自当前循环帐户的SQL函数,并且每个帐户ID收集上述每个帐户的所有相关数据,例如:变量1,2,表等。因此,根据帐户ID,它返回所有变量以及包含3列和所有行的表。
因此,为简化起见,对于每个帐户ID,XML文件都需要将上述结构附加到文件中。现在,当我尝试使用所有这些不同的部分创建XML文件时,我的困境就出现了。
第一个问题是如何将表信息和变量信息组合到一个XML树中。我知道可以从表中创建带有元素的XML林,但问题是每个帐户都有一组可变数据和一个表。我已经考虑了table_to_xml,但这直接来自一个表,我不知道如何在table / xml之前附加变量元素。
我考虑过做文本数组:
for rec in execute cmd
loop
cmd:= 'select xmlelement(name "Account",
xmlelement(name "Variable1", '||var1||'))';
execute cmd into vtext
varray[n] := vtext;
n++
end loop;
然后可能将嵌套在xmlelement中的表作为文本数组。继续嵌套,直到我拥有所有的为止,然后在它们结合在一起后将它们发送给XML。
下一个问题是将所有这些帐户合并到同一XML文件中的一个总体元素中。
如果有人对如何解决这个问题有任何想法,我将非常感谢帮助。我觉得我在思考整个过程,或者在SQL中做起来太荒谬了,也许我应该用像Python这样的脚本语言来尝试这些操作。
答案 0 :(得分:0)
问题的解决方案非常简单。将所有数据放入临时表并连接。特别是为我想要的输出做这个的方法:
-- FUNCTION AFTER CREATE AND DECLARES
v_cmd := 'select Accounts from <table>';
final_xml := '<?xml version="1.0"?><Accounts>';
for record in execute v_cmd
loop
<generate Account data into SQL variables>
-- Check if temp table exists, then create P1
v_table_name1 := '<temp_table1>';
IF EXISTS (select 1 from information_schema.tables
where table_schema = '<schema>' and table_name = <temp_table1>) THEN
v_s_cmd := 'DROP TABLE '||<temp_table1>;
execute v_s_cmd;
END IF;
v_s_cmd := 'CREATE TABLE <temp_table1>
(variable1 varchar, variable2 varchar, ...)';
execute v_s_cmd;
v_s_cmd := 'INSERT INTO <temp_table1>
(variable1, variable2, ...)
VALUES ('||coalesce(quote_literal(Account.variable1),'NULL')||','
''||coalesce(quote_literal(Account.variable2),'NULL')||',' ...)'';
execute v_s_cmd;
<generate multiple row data to be elements of the above Account>
-- Check if temp table exists, then create P1
v_table_name2 := '<temp_table2>';
IF EXISTS (select 1 from information_schema.tables
where table_schema = '<schema>' and table_name = <temp_table2>) THEN
v_s_cmd := 'DROP TABLE '||<temp_table2>;
execute v_s_cmd;
END IF;
v_s_cmd := 'CREATE TABLE <temp_table2(Column1, Column2, Column3)';
execute v_s_cmd;
column_id = record.row_id;
for column_record in
SELECT Column1, Column2, Column3 FROM <column_data_source>
WHERE data_id = column_id ORDER BY Column1, Column2, Column3
loop
v_s_cmd := 'INSERT INTO '||<temp_table2>||
'(Column1, Column2, Column3, column_id) SELECT
'||quote_literal(column_record.Column1)||',
'||quote_literal(column_record.Column2)||',
'||quote_literal(column_record.Column2)||',
'''||column_id||''';';
execute v_s_cmd;
end loop;
-- get var data
v_s_cmd := '(select regexp_replace((
XMLElement(name Account,
XMLForest(variable1, variable2 ...)))::text,
''</Account>'','''',''g'') as var_d
FROM <temp_table1>)';
execute v_s_cmd into var_data;
-- get Table data
v_s_cmd := 'select XMLElement(name Row,
XMLForest(Column1, Column2, Column3)) as test
FROM '||<temp_table2>;
table_rec := '<Table>';
-- concatenate to variable
for row_rec in execute v_s_cmd
loop
table_rec := table_rec || row_rec.test;
end loop;
table_rec := table_rec||'</Table></Account>';
-- complete XML part and concatenate to main xml variable
final_xml := final_xml || var_data || s_a_rec;
v_s_cmd := 'drop table '||temp_table1;
execute v_s_cmd;
v_s_cmd := 'drop table '||temp_table2;
execute v_s_cmd;
END LOOP;
final_xml := final_xml || '</Accounts>';
final_xml := XMLPARSE(DOCUMENT final_xml);
create table schema.temp_final_xml(xmlcode varchar);
insert into schema.temp_final_xml(xmlcode) VALUES (final_xml);
v_s_cmd := 'COPY (select xmlcode from schema.temp_final_xml)
TO ''/filepath/file.xml''';
execute v_s_cmd;
drop table schema.temp_final_xml;
如果有更简洁的方法来执行此操作,我很想知道。我把我的大脑震撼了几天才想出来。