سؤال

وأنا أحاول أن تولد وثيقة XML من قاعدة بيانات SQL Server 2005 باستخدام "FOR XML" بناء.

وهناك نوعان من الجداول بسيطة في قاعدة البيانات مع واحدة إلى العديد من العلاقة:

1) مجلات

 | Id | Number | Name       |
 ----------------------------
 | 53 | 0001   | Magazine 1 |
 | 54 | 0002   | Magazine 2 |
 | 55 | 0003   | Magazine 3 |

2) المواد

 | Id |   Title   | MagazineId | Size |
 --------------------------------------
 | 1  | Article 1 |        53  | 1205 |
 | 2  | Article 2 |        53  | 817  |
 | 3  | Article 3 |        54  | 1570 |
 | 4  | Article 4 |        54  | 2510 |
 | 5  | Article 5 |        55  | 910  |

لنفترض لدي للعثور على جميع المجلات التي لديها مقال مع حجم أكبر من 1000 ولإنتاج XML التالية:

<Magazines>
    <Magazine Id="53">
      <Number>0001</Number>
      <Articles>
        <Article Id="1">
           <Title>Article 1</Title>
           <Size>1205</Size>
        </Article>
      </Articles>
    </Magazine>
    <Magazine Id="54">
      <Number>0002</Number>
      <Articles>
        <Article Id="3">
          <Title>Article 3</Title>
          <Size>1570</Size>
        </Article>
        <Article Id="4">
          <Title>Article 4</Title>
          <Size>2510</Size>
        </Article>
      </Articles>
    </Magazine>
</Magazines>

وأنا أحاول أن تنتج مثل هذا أكس باستخدام وضع "PATH":

SELECT Magazines.Id AS "@Id",
       Magazines.Number AS "Number",
       Articles.Id AS "Articles/Article/@Id",
       Articles.Title AS "Articles/Article/Title",
       Articles.Size AS "Articles/Article/Size"
FROM Magazines INNER JOIN Articles ON Magazines.Id = Articles.MagazineId
WHERE Articles.Size > 1000
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE

ووسينتج XML التالية:

<Magazines>
  <Magazine Id="53">
    <Number>0001</Number>
    <Articles>
      <Article Id="1">
        <Title>Article 1</Title>
        <Size>1205</Size>
      </Article>
    </Articles>
  </Magazine>
  <Magazine Id="54">
    <Number>0002</Number>
    <Articles>
      <Article Id="3">
        <Title>Article 3</Title>
        <Size>1570</Size>
      </Article>
    </Articles>
  </Magazine>
  <Magazine Id="54">
    <Number>0002</Number>
    <Articles>
      <Article Id="4">
        <Title>Article 4</Title>
        <Size>2510</Size>
      </Article>
    </Articles>
  </Magazine>
</Magazines>

وحتى أن هناك عنصرين لمجلة مع معرف = "54" (واحدة لكل مادة)، وهذه هي المشكلة.

ويمكنني كتابة الاستعلام باستخدام استعلام فرعي مثل هذا:

SELECT M.Id AS "@Id",
       M.Number AS "Number",
    (SELECT Articles.Id AS "@Id",
               Articles.Title AS "Title",
               Articles.Size AS "Size"
  FROM Articles
  WHERE Articles.MagazineId = M.Id
  FOR XML PATH('Article'), ROOT('Articles'), TYPE
    )
FROM Magazines AS M 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE

وهذا ينتج XML التالية:

<Magazines>
  <Magazine Id="53">
    <Number>0001</Number>
    <Articles>
      <Article Id="1">
        <Title>Article 1</Title>
        <Size>1205</Size>
      </Article>
      <Article Id="2">
        <Title>Article 2</Title>
        <Size>817</Size>
      </Article>
    </Articles>
  </Magazine>
  <Magazine Id="54">
    <Number>0002</Number>
    <Articles>
      <Article Id="3">
        <Title>Article 3</Title>
        <Size>1570</Size>
      </Article>
      <Article Id="4">
        <Title>Article 4</Title>
        <Size>2510</Size>
      </Article>
    </Articles>
  </Magazine>
  <Magazine Id="55">
    <Number>0003</Number>
    <Articles>
      <Article Id="5">
        <Title>Article 5</Title>
        <Size>910</Size>
      </Article>
    </Articles>
  </Magazine>
</Magazines>

ولكن باستخدام استعلام فرعي I لا يمكن تصفية المجلات أعمدة المواد (بدون استفسارات إضافية معقدة).

ووضع "FOR AUTO XML" غير مناسب، لأنها بسيطة جدا ولا يدعم بعض الميزات "PATH" (مثل سمات باستخدام @، ROOT، الخ ..)

وهكذا، هل هناك أي احتمال في وضع "PATH" لتجميع البيانات الجدول الداخلية كما هو الحال في "AUTO" واسطة؟

وشكرا لك!

هل كانت مفيدة؟

المحلول

حسنا، يمكنك الحصول على خطوة واحدة لتحديد "حجم> 1000" داخل فرعي الخاص بك:

SELECT M.Id AS "@Id",
       M.Number AS "Number",
    (SELECT Articles.Id AS "@Id",
               Articles.Title AS "Title",
               Articles.Size AS "Size"
     FROM Articles
     WHERE Articles.MagazineId = M.Id
           AND Articles.Size > 1000
     FOR XML PATH('Article'), ROOT('Articles'), TYPE
    )
FROM Magazines AS M 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE

ما كنت في عداد المفقودين الآن هو حقيقة أنك سوف لا يزال الحصول على المجلات التي ليس لها المواد مع حجم> 1000. يمكنك إزالة تلك شيئا من هذا القبيل:

SELECT M.Id AS "@Id",
       M.Number AS "Number",
    (SELECT Articles.Id AS "@Id",
               Articles.Title AS "Title",
               Articles.Size AS "Size"
      FROM Articles
      WHERE Articles.MagazineId = M.Id
            AND Articles.Size > 1000
      FOR XML PATH('Article'), ROOT('Articles'), TYPE
    )
FROM Magazines AS M 
WHERE EXISTS(SELECT * FROM Articles 
             WHERE Articles.MagazineId = M.Id 
               AND Articles.Size > 1000)
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE

و(غير مجربة، وأنا لم يكن لديك ملقم SQL في متناول اليد الآن).

هل هذا العمل بالنسبة لك؟ هل تعطيك المجلات والمواد كنت تبحث عنه؟

ومارك

نصائح أخرى

استخدم FOR XML صريح. هو أطول كود لكتابة لكنها تختفي مشكلات الأداء استفزاز من قبل الاستعلامات الفرعية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top