簡體   English   中英

如何從 PostgreSQL 1:n 表中生成 XML 響應?

[英]How do I produce an XML response from PostgreSQL 1:n tables?

我有表“客戶”:

id  name     registered_on  status
--  -------  -------------  ------
 1  Alice    2020-03-04     a     
 2  Vincent  2020-03-05     p     
 3  Anne     2020-03-06     a     

和表“帳戶”:

client_id  account_number  type  balance
---------  --------------  ----  -------
        1  300-1           CHK       100
        2  307-5           SAV        24
        2  307-6           CHK       350

我在DB Fiddle中創建了它們(對於我之前問過的關於生成 JSON 的類似問題)。

現在,我需要一個 SQL 查詢來生成 1:n XML 文檔:

<client id="1" name="Alice" registered_on="2020-03-04" status="a">
  <account account_number="300-1" type="CHK" balance="100" />
</client>

<client id="2" name="Vincent" registered_on="2020-03-05" status="p">
  <account account_number="307-5" type="SAV" balance="24" />
  <account account_number="307-6" type="CHK" balance="350" />
</client>

<client id="3" name="Anne" registered_on="2020-03-06" status="a" />

表格之間存在 1:n 的關系,並且某些客戶可能沒有帳戶(例如“Anne”)。 結果是我知道該怎么做的簡單連接(可能是外部連接)。 我只是不知道如何從中生成 XML 文檔。

如果它更容易/更短,我願意接受替代 XML 結果,只要它代表相同的數據; 例如,使用標簽而不是屬性。

在嘗試了一堆選項后,我能夠找到答案。

原始格式:帶屬性

可以使用外連接生成 XML 結果:

select
  xmlserialize(content -- remove this line to keep as XML instead of VARCHAR
  xmlagg(r)
  as text) -- remove this line to keep as XML instead of VARCHAR
from (
  select
    xmlelement(name client,
      xmlattributes(c.id, c.name, c.registered_on, c.status),
      case when count(a.client_id) > 0 then 
        xmlagg(xmlelement(name account, 
                 xmlattributes(a.account_number, a.type, a.balance) ))
      end
    ) as r
  from client c
  left join account a on a.client_id = c.id
  group by c.id
) s

或使用子查詢(更短但性能更低):

select
  xmlserialize(content -- remove this line to keep as XML instead of VARCHAR
  xmlagg(
  xmlelement(name client, xmlattributes(id, name, registered_on, status),
    ( select xmlagg(xmlelement(name account,
             xmlattributes(a.account_number, a.type, a.balance)
      )) from account a where a.client_id = c.id
    )
  ))
  as text) -- remove this line to keep as XML instead of VARCHAR
from client c;

結果:

<client id="1" name="Alice" registered_on="2020-03-04" status="a">
  <account account_number="300-1" type="CHK" balance="100.00" />
</client>
<client id="2" name="Vincent" registered_on="2020-03-05" status="p">
  <account account_number="307-5" type="SAV" balance="24.00" />
  <account account_number="307-6" type="CHK" balance="350.00" />
</client>
<client id="3" name="Anne" registered_on="2020-03-06" status="a" />

替代格式:無屬性

有些人喜歡完全避免使用屬性並總是使用標簽。 這也可以使用:

select 
  xmlserialize(content -- remove this line to keep as XML instead of VARCHAR
  xmlagg(xmlelement(name client,
    xmlforest(id, name, registered_on, status), 
    ( select xmlagg(xmlelement(name account, 
             xmlforest(a.account_number, a.type, a.balance))) 
      from account a where a.client_id = c.id 
    )
  ))
  as text) -- remove this line to keep as XML instead of VARCHAR
from client c;

結果:

<client>
  <id>1</id>
  <name>Alice</name>
  <registered_on>2020-03-04</registered_on>
  <status>a</status>
  <account>
    <account_number>300-1</account_number>
    <type>CHK</type>
    <balance>100.00</balance>
  </account>
</client>
<client>
  <id>2</id>
  <name>Vincent</name>
  <registered_on>2020-03-05</registered_on>
  <status>p</status>
  <account>
    <account_number>307-5</account_number>
    <type>SAV</type>
    <balance>24.00</balance>
  </account>
  <account>
    <account_number>307-6</account_number>
    <type>CHK</type>
    <balance>350.00</balance>
  </account>
</client>
<client>
  <id>3</id>
  <name>Anne</name>
  <registered_on>2020-03-06</registered_on>
  <status>a</status>
</client>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM