2013-02-22 60 views
0

我将与我的期望的输出是什么奔涌:生成XML在PostgreSQL函数和变量和表格

<?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

我已经考虑用变量创建一个表格,然后创建

部分的表格,并使用可以匹配主变量表的关系ID,但问题仍然归结为试图插入多行单行,使这样的语句不可能: – BagoDev2013-02-22 23:05:24

+0

select XMLElement( name noi, XMLForest(z.var1,z.var2,z.var3,z.var4), XMLElement(name Table,XMLForest(row1col1,row1col2) )) FROM(从表1 选择。*一 加入关于((a.something = b.something 表2 b)和(a.something = b.something)) 其中b.dt为空以及b。 dt为空)z – BagoDev 2013-02-22 23:08:07

回答

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; 

如果执行此操作我很想知道它一个更清洁的方式。我想了几天就想出了这个想法。