2012-06-29 47 views
5

Tôi đã thử sử dụng "FOR XML PATH", "FOR XML EXPLICIT" và "FOR XML AUTO" nhưng dữ liệu không bao giờ được cấu trúc chính quyền thừa kế.Cách trả về XML từ SQL Server 2008 được cấu trúc với nhiều lựa chọn chia sẻ một phụ huynh chung

Về cơ bản, tôi có một bảng cha (Khách hàng) và 3 bảng con. Mỗi bảng có một cột customerid. Có một mối quan hệ một-nhiều từ bảng Khách hàng đến từng bảng con.

Ví dụ: tôi có bảng "Khách hàng" và tôi có 3 bảng khác - Sản phẩm, Sở thích và Phương tiện - tất cả đều liên quan đến bảng Khách hàng bởi khách hàng.

<Customers> 
    <Customer customerid="1" name="Fred"> 
     <Products> 
      <Product productname="table" /> 
      <Product productname="chair" /> 
      <Product productname="wardrobe" /> 
     </Products> 
     <Hobbies> 
      <Hobby hobbyname="Golf" /> 
      <Hobby hobbyname="Swimming" /> 
     </Hobbies> 
     <Vehicles> 
      <Vehicle name="Car" color="Red" /> 
      <Vehicle name="Bicycle" color="Blue" /> 
     </Vehicles> 
    </Customer> 
    <Customer customerid="2" name="Sue"> 
     <Products> 
      <Product productname="CD player" /> 
      <Product productname="Picture frame" /> 
     </Products> 
     <Hobbies> 
      <Hobby hobbyname="Dancing" /> 
      <Hobby hobbyname="Reading" /> 
     </Hobbies> 
     <Vehicles> 
      <Vehicle name="Car" color="Yellow" /> 
     </Vehicles> 
    </Customer> 
</Customers> 

Trả lời

4

Sử dụng FOR XML RAW

IF OBJECT_ID ('tempdb..#customer') IS NOT NULL DROP TABLE #Customer 
IF OBJECT_ID ('tempdb..#product') IS NOT NULL DROP TABLE #product 
IF OBJECT_ID ('tempdb..#vehicle') IS NOT NULL DROP TABLE #Vehicle 
IF OBJECT_ID ('tempdb..#hobbies') IS NOT NULL DROP TABLE #Hobbies 

CREATE TABLE #Customer (id INT,name NVARCHAR(20)) 
INSERT INTO #customer SELECT 1,'Fred' UNION ALL SELECT 2,'Sue' 

CREATE TABLE #product(customer_id INT, name NVARCHAR(20)) 
INSERT INTO #product 
SELECt 1 AS id, 'table' as product 
UNION ALL SELECT 1 AS id, 'chair' as product 
UNION ALL SELECT 1 AS id, 'wardrobe' as product 
UNION ALL SELECT 2 AS id, 'CD Player' as product 
UNION ALL SELECT 2 AS id, 'Picture Frame' as product 


CREATE TABLE #vehicle(customer_id INT, name NVARCHAR(20),colour NVARCHAR(20)) 
INSERT INTO #vehicle 
SELECt 1 AS id, 'Car' as vehicle,'red' as colour 
UNION ALL SELECT 1 AS id, 'bicycle' as vehicle,'Blue' AS colour 
UNION ALL SELECT 2 AS id, 'Car' as vehicle, 'Yellow' as colour 


CREATE TABLE #hobbies(customer_id INT, name NVARCHAR(20)) 
INSERT INTO #hobbies 
SELECt 1 AS id, 'Golf' as name 
UNION ALL SELECT 1 AS id, 'Swimming' as name 
UNION ALL SELECT 2 AS id, 'Dancing' as name 
UNION ALL SELECT 2 AS id, 'Reading' as name 

SELECT 
c.id AS id 
,c.name AS name 
,(SELECT p.name 
    FROM #product p 
    WHERE p.customer_id = c.id 
    FOR XML RAW('Products'),TYPE) AS Products 
,(SELECT h.name 
    FROM #hobbies h 
    WHERE h.customer_id = c.id 
    FOR XML RAW('Hobbies'),TYPE) AS Hobbies 
,(SELECT v.name,v.colour 
    FROM #vehicle v 
    WHERE v.customer_id = c.id 
    FOR XML RAW('Vehicle'),TYPE) AS Vehicle 
FROM #customer c 
FOR XML RAW('Customer'), ROOT('Customers') 
5

Hãy thử một cái gì đó như thế này - -

mã SQL để đạt được các loại sau đây của các cấu trúc là gì nó sử dụng CHO XML PATH và subselects để tạo ra các "liên kết" các nút con cho một khách hàng cụ thể (Tôi giới hạn số này thành hai bảng phụ - nhưng bạn sẽ nhận được "ý chính" của nó và có thể mở rộng nó cho bất kỳ số phụ được liên kết nào):

SELECT 
    CustomerID AS '@CustomerID', 
    CustName AS '@Name', 

    (SELECT ProductName AS '@productname' 
    FROM dbo.Products p 
    WHERE p.CustomerID = c.CustomerID 
    FOR XML PATH('Product'), TYPE) AS 'Products', 

    (SELECT HobbyName AS '@hobbyname' 
    FROM dbo.Hobbies h 
    WHERE h.CUstomerID = c.CustomerID 
    FOR XML PATH('Hobby'), TYPE) AS 'Hobbies' 
FROM 
    dbo.Customers c 
FOR XML PATH('Customer'), ROOT('Customers') 

Cung cấp cho tôi một cái gì đó đầu ra như:

<Customers> 
    <Customer CustomerID="1" Name="Fred"> 
    <Products> 
     <Product productname="Table" /> 
     <Product productname="Wardrobe" /> 
     <Product productname="Chair" /> 
    </Products> 
    <Hobbies> 
     <Hobby hobbyname="Golf" /> 
     <Hobby hobbyname="Swimming" /> 
    </Hobbies> 
    </Customer> 
    <Customer CustomerID="2" Name="Sue"> 
    <Products> 
     <Product productname="CD Player" /> 
     <Product productname="Picture frame" /> 
    </Products> 
    <Hobbies> 
     <Hobby hobbyname="Dancing" /> 
     <Hobby hobbyname="Gardening" /> 
     <Hobby hobbyname="Reading" /> 
    </Hobbies> 
    </Customer> 
</Customers> 
+0

Would sử dụng XML PATH có hiệu quả hơn so với XML RAW cho các tập dữ liệu lớn hơn? – Dibstar

+0

@Davin: không chắc chắn về * hiệu quả * - Tôi thấy FOR XML PATH dễ đọc hơn và nó mang lại cho tôi sự linh hoạt hơn để định dạng đầu ra XML –

-1
USE [EAPP_BranchDb] 
GO 

/****** Object: StoredProcedure [dbo].[SP_procXMLOutput] Script Date: 09/05/2013 15:14:05 ******/ 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 


CREATE PROCEDURE [dbo].[SP_procXMLOutput] 
        @Data XML OUTPUT 
AS 
BEGIN 

DECLARE @myDoc xml, 
     @myDoc1 xml, 
     @var_Doc1 nvarchar(max), 
     @myDoc2 xml, 
     @var1 nvarchar(max), 
     @var2 nvarchar(max), 
     @var3 nvarchar(max), 
     @var_id as int, 
     @var_id1 as nvarchar(10), 
     @var_grp_id1 as nvarchar(10), 
     @var_parent_id as bigint, 
     @var_grp_id as nvarchar(10), 
     @var_parent_type as nvarchar(1), 
     @var_type as nvarchar(10), 
     @xml XML, 
     @grp1 nvarchar(max), 
     @grp2 nvarchar(max) 

DECLARE xml_cur_id CURSOR FOR 
SELECT id, parent_id, grp_id, parent_type,type FROM xml_table where parent_type='P' order by id 

DECLARE xml_cur_grpid CURSOR FOR 
SELECT GRP_ID FROM xml_table WHERE parent_id=6 and parent_type='C' group by GRP_ID 

BEGIN 
    SET @myDoc = N'<frameSet label="Personal Details" id="1"   
        </frameSet'; 

    SET @var_Doc1='<field pid="6" type="ROW" /</field';    
    OPEN xml_cur_id 
     FETCH NEXT FROM xml_cur_id INTO @var_id, @var_parent_id, @var_grp_id, @var_parent_type,@var_type 
      WHILE @@FETCH_STATUS = 0 
      BEGIN 

      IF @var_type<'TABLE' and @var_parent_type='P' 
      BEGIN 
       SET @myDoc1=(SELECT id, name, type, isMandtory, isDependent, isDependentValue,dataType, lookupPath, lookupName, defaultValue, minDate, maxDate, fieldLabel, maxLength, readonly, disabled, onChangeEvent, reloadEvent, validationMessage, tabindex FROM xml_table WHERE [email protected]_id FOR XML RAW('field')) 
       SET @myDoc.modify('insert sql:variable("@myDoc1") as last into (/frameSet)[1] ') 
      END 


      IF @var_type='TABLE' and @var_parent_type='P' 
      BEGIN 
       /*table parent creation START*/ 
       SET @myDoc1=(SELECT id, name, type,fieldLabel FROM xml_table WHERE [email protected]_id FOR XML RAW('field')) 
       SET @myDoc.modify('insert sql:variable("@myDoc1") as last into (/frameSet)[1] ') 
       /*table parent creation END*/ 

       /*table COLUMN creation START*/ 
       SELECT @var1=(SELECT type,fieldLabel FROM XML_RELATION_TABLE WHERE Parent_id=6 order by id FOR XML RAW('field')) 
       SELECT @var2=(SELECT '<field type="ROW"'[email protected]+'</field') 
       SELECT @[email protected] 
       SET @[email protected]_id 
       /*table COLUMN creation START*/ 
       /*TABLE CHILD row creation START*/ 
       SET @var3='' 
       OPEN xml_cur_grpid 
        FETCH NEXT FROM xml_cur_grpid INTO @var_grp_id1 
         WHILE @@FETCH_STATUS = 0 
         BEGIN 

          SELECT @grp1=(SELECT id, name, type, isMandtory, isDependent, isDependentValue,dataType, lookupPath, 
          lookupName, defaultValue, minDate, maxDate, fieldLabel, maxLength, 
          readonly, disabled, onChangeEvent, reloadEvent, validationMessage, tabindex FROM xml_table 
          WHERE [email protected]_parent_id and parent_type='C' and [email protected]_grp_id1 order by id 
          FOR XML RAW('field')) 

          SELECT @grp2=(SELECT '<field type="ROW"'[email protected]+'</field') 
          SET @[email protected][email protected] 

         FETCH NEXT FROM xml_cur_grpid INTO @var_grp_id1 
         END 
       CLOSE xml_cur_grpid 
       DEALLOCATE xml_cur_grpid    
       /*TABLE CHILD row creation END*/ 


       SELECT @[email protected][email protected] 
       SET @myDoc.modify('insert sql:variable("@myDoc1") into (/frameSet/field[@id=sql:variable("@var_id1")])[1] ') 
       SET @var2='' 
       SET @var3='' 
      END 

      FETCH NEXT FROM xml_cur_id INTO @var_id, @var_parent_id, @var_grp_id, @var_parent_type,@var_type 
      END 
    CLOSE xml_cur_id 
    DEALLOCATE xml_cur_id 


    SET @[email protected] 

END   

END  

GO 
+0

MÃ ĐỐI VỚI XML GENERATION TỪ SQL SERVER2008 –

+0

Tôi chắc chắn điều này có ích cho bạn nhưng làm thế nào nó có liên quan đến câu hỏi? –

2
select 
    c.customerid, 
    c.name, 
    (
     select p.productname 
     from Products as p 
     where p.customerid = c.customerid 
     for xml raw('Product'), root('Products'), type 
    ), 
    (
     select h.hobbyname 
     from Hobbies as h 
     where h.customerid = c.customerid 
     for xml raw('Hobby'), root('Hobbies'), type 
    ), 
    (
     select v.name, v.color 
     from Vehicles as v 
     where v.customerid = c.customerid 
     for xml raw('Vehicle'), root('Vehicles'), type 
    ) 
from Customers as c 
for xml raw('Customer'), root('Customers') 

=> sql fiddle demo

0
DECLARE @sampleCount int =10 
SET STATISTICS TIME ON 


SELECT 

    (SELECT TOP (@sampleCount) * FROM [Table1]TABLESAMPLE(100 PERCENT) FOR XML PATH('tbl1'), TYPE) AS 'tbl1', 
    (SELECT top (@sampleCount) * FROM [Table2] TABLESAMPLE(100 PERCENT) FOR XML PATH('tbl2'), TYPE) AS 'tbl2', 
    (SELECT top (@sampleCount) * FROM [Table3] TABLESAMPLE(100 PERCENT) FOR XML PATH('tbl3'), TYPE) AS 'tbl3' 


FOR XML PATH(''), ROOT('Table')