PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

3 टेबल के साथ एक्सएमएल से पोस्टग्रेएसक्यूएल

आपके पास नेस्टेड टेबल के तीन स्तर हैं।

नमूना डेटा:

CREATE TABLE a(
  a_id integer primary key,
  name text
);

CREATE TABLE b(
  b_id integer primary key,
  a_id integer references a(a_id),
  val text
);

CREATE TABLE c(
  c_id serial primary key,
  b_id integer references b(b_id),
  blah text
);

INSERT INTO a(a_id, name) VALUES (1, 'fred'),(2, 'bert');

INSERT INTO b(b_id, a_id, val) VALUES 
(11, 1, 'x'), (12, 1, 'y'), (21, 2, 'a'), (22, 2, 'b');

INSERT INTO c(b_id, blah) VALUES
(11, 'whatever'), (11, 'gah'), (12, 'borkbork'), (22, 'fuzz');

विधि 1:लेफ्ट जॉइन करें, क्लाइंट में XML को हैंडल करें

इसे संभालने का सबसे आसान तरीका है कि सभी तीन टेबलों पर बाएं शामिल हों, जो सबसे बाहरी से अंतरतम तक ऑर्डर किए गए हों। फिर आप परिणाम सेट को पुनरावृत्त करते हैं, एक तत्व को बंद करते हैं और दूसरे को खोलते हैं जब भी उस स्तर पर विषय बदलता है।

select *
from a left join b on (a.a_id = b.a_id)
       left join c on (b.b_id = c.b_id)
order by a.a_id, b.b_id, c.c_id;

फिर लौटाई गई पंक्तियों पर लूप करें, और प्रत्येक पंक्ति के लिए, छद्म कोड :

cur_row = get_new_row()

if (cur_row[b_id] != prev_row[b_id]) {
   emit_close_tableb();
}
if (cur_row[a_id] != prev_row[a_id]) {
   emit_close_tablea();
   emit_open_tablea(cur_row);
}
if (cur_row[b_id] != prev_row[b_id]) {
   emit_open_tableb(cur_row);
}
emit_tablec(cur_row);

prev_row = cur_row;

एक्सएमएल लिखने के लिए आप XMLWriter जैसी किसी चीज़ का इस्तेमाल करेंगे . क्वेरी डेटा को पढ़ने के लिए आप पीडीओ या आप जो भी ड्राइवर पसंद करते हैं जैसे कुछ का उपयोग कर सकते हैं। यदि डेटा सेट बड़ा है तो डेटा को पढ़ने के लिए कर्सर का उपयोग करने पर विचार करें।

यह अच्छी तरह से काम करता है, लेकिन यह एक लॉट . को स्थानांतरित करता है अतिरिक्त डेटा, चूंकि आप n transfer स्थानांतरित करते हैं प्रत्येक n . के लिए बाहरी तालिका के डेटा की प्रतियां इससे जुड़ी आंतरिक तालिका की पंक्तियाँ।

एक्सचेंज किए गए अतिरिक्त डेटा को कम करने के लिए आप केवल बाहरी तालिकाओं के लिए आईडी का चयन कर सकते हैं

select a.a_id, b.b_id, c.*
from a left join b on (a.a_id = b.a_id)
       left join c on (b.b_id = c.b_id)
order by a.a_id, b.b_id, c.c_id;

... फिर जब आप एक नई टेबल/टेबलब पर स्विच करते हैं, SELECT फिर इसकी बाकी पंक्तियाँ। ऐसा करने के लिए आप शायद दूसरे कनेक्शन का उपयोग करेंगे ताकि आप मुख्य कनेक्शन पर परिणाम सेट और कर्सर स्थिति को बाधित न करें, जिससे आप पंक्तियां पढ़ रहे हैं।

विधि 2:यह सब PostgreSQL में करें

छोटे डेटा सेट के लिए, या बड़े डेटा सेट के आंतरिक स्तरों के लिए, आप XML दस्तावेज़ बनाने के लिए PostgreSQL के XML समर्थन का उपयोग कर सकते हैं, जैसे:

WITH xmlinput AS (
  SELECT a, b, c
  FROM a
  LEFT JOIN b ON (a.a_id = b.a_id)
  LEFT JOIN c on (b.b_id = c.b_id)
  ORDER BY a.a_id, b.b_id, c.c_id
)
SELECT
  XMLELEMENT(name items,
    xmlagg(
      XMLELEMENT(name a,
        XMLFOREST((a).a_id AS a_id, (a)."name" AS name),
        b_xml
      )
    ORDER BY (a).a_id)
  ) AS output
FROM
(
  SELECT
    a,
    xmlagg(
      XMLELEMENT(name b,
        XMLFOREST((b).b_id AS b_id, (b).val AS val),
        c_xml
      )
    ORDER BY (b).b_id)
    AS b_xml
  FROM
  (
    SELECT
      a, b,
      xmlagg(
        XMLELEMENT(name c,
          XMLFOREST((c).c_id AS c_id, (c).blah AS blah)
        )
      ORDER BY (c).c_id)
      AS c_xml
    FROM xmlinput
    GROUP BY a, b
  ) c_as_xml
  GROUP BY a
) b_as_xml;

... लेकिन वास्तव में, आपको उस तरह का कोड लिखने के लिए किसी प्रकार का मर्दवादी होना होगा। हालांकि यह काफी तेज साबित हो सकता है।

क्वेरी को समझने के लिए आपको PostgreSQL XML डॉक्स को पढ़ना होगा . SQL/XML समिति ने अजीब वाक्य रचना का सपना देखा था, हमें दोष न दें।

यह भी ध्यान दें कि पंक्ति-चर इसे व्यवस्थित रखने के लिए उपरोक्त कोड में भारी उपयोग किया जाता है। a , b और c क्वेरी की बाहरी परतों को पूरी पंक्तियों के रूप में पास किया जाता है। यह उपनामों के साथ खिलवाड़ करने की आवश्यकता से बचा जाता है जब नाम टकराते हैं। सिंटैक्स (a).a_id , आदि का अर्थ है "a_id पंक्ति-चर का क्षेत्र a "। विवरण के लिए PostgreSQL मैनुअल देखें।

उपरोक्त एक बेहतर एक्सएमएल संरचना का उपयोग करता है (नीचे टिप्पणियां देखें)। यदि आप तत्वों को नहीं विशेषताओं का उत्सर्जन करना चाहते हैं, तो आप XMLFOREST . को बदल सकते हैं XMLATTRIBUTES पर कॉल करता है कॉल।

आउटपुट:

<items><a><a_id>1</a_id><name>fred</name><b><b_id>11</b_id><val>x</val><c><c_id>1</c_id><blah>whatever</blah></c><c><c_id>2</c_id><blah>gah</blah></c></b><b><b_id>12</b_id><val>y</val><c><c_id>3</c_id><blah>borkbork</blah></c></b></a><a><a_id>2</a_id><name>bert</name><b><b_id>21</b_id><val>a</val><c/></b><b><b_id>22</b_id><val>b</val><c><c_id>4</c_id><blah>fuzz</blah></c></b></a></items>

या, सुंदर-मुद्रित:

<?xml version="1.0" encoding="utf-16"?>
<items>
    <a>
        <a_id>1</a_id>
        <name>fred</name>
        <b>
            <b_id>11</b_id>
            <val>x</val>
            <c>
                <c_id>1</c_id>
                <blah>whatever</blah>
            </c>
            <c>
                <c_id>2</c_id>
                <blah>gah</blah>
            </c>
        </b>
        <b>
            <b_id>12</b_id>
            <val>y</val>
            <c>
                <c_id>3</c_id>
                <blah>borkbork</blah>
            </c>
        </b>
    </a>
    <a>
        <a_id>2</a_id>
        <name>bert</name>
        <b>
            <b_id>21</b_id>
            <val>a</val>
            <c />
        </b>
        <b>
            <b_id>22</b_id>
            <val>b</val>
            <c>
                <c_id>4</c_id>
                <blah>fuzz</blah>
            </c>
        </b>
    </a>
</items>

कृपया बेहतर XML उत्सर्जित करें

एक तरफ ध्यान दें, एक्सएमएल में उस तरह की विशेषताओं का उपयोग करना आकर्षक लगता है, लेकिन इसके साथ काम करना मुश्किल और बदसूरत हो जाता है। कृपया सामान्य XML तत्वों का उपयोग करें:

  <Table 1>
    <Nr>1</Nr>
    <Name>blah</Name>
     <Table 2>
       <Nr>1</Nr>
       <Table 3>
          <Col1>42</Col1>
          <Col2>...</Col2>
          <Col3>...</Col3>
          <Col4>...</Col4>
          ...
       </Table 3>
     </Table 2>
   </Table 1>



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL एक फ़ंक्शन में मेरी क्वेरी को अलग तरीके से क्यों मानता है?

  2. वर्चर पर एसक्यूएल इंडेक्सिंग

  3. स्प्रिंग बूट एप्लिकेशन हिकारी-पूल-1 पर अटक जाता है - प्रारंभ...

  4. PostgreSQL नेस्टेड JSON क्वेरी

  5. Qt एप्लिकेशन से वर्तमान PostgreSQL उपयोगकर्ता की भूमिका की जांच कैसे करें?