如何从SQL Server 2008的多项选择共享一个共同的父结构返回XML(How to retu

2019-09-18 18:04发布

我一直在使用“FOR XML PATH”试过了,“FOR XML EXPLICIT”和“FOR XML AUTO”,但数据不会与正确的层次结构构成。

基本上,我有一个父表(客户)和3个表。 每个表都有一个CustomerID列。 有一个从客户表到每个3个表的一个一对多的关系。

作为一个模拟的例子,我有一个父“客户”表,我还有其他3个表 - 产品,爱好和车辆 - 全部由一个客户ID相关的客户表。

什么是SQL代码来实现以下一种结构 -

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

Answer 1:

尝试这样的事情-它使用XML PATH和子选择创建“链接”给定客户子节点( 我限制这两个分表-但你应该得到它的“要点”,并能够扩展它任何数量的链接的子表 ):

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')

给我一个输出类似:

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


Answer 2:

使用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')


Answer 3:

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拨弄演示



Answer 4:

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')


Answer 5:

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 id=@var_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 id=@var_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"'+@var1+'</field')
                SELECT @myDoc1=@var2
                SET @var_id1=@var_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 parent_id=@var_parent_id and parent_type='C' and grp_id=@var_grp_id1 order by id
                            FOR XML RAW('field'))

                            SELECT @grp2=(SELECT '<field type="ROW"'+@grp1+'</field')
                            SET @var3=@var3+@grp2

                        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 @myDoc1=@var2+@var3
                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 @Data=@myDoc

END        

END    

GO


文章来源: How to return XML from SQL Server 2008 that is structured with multiple selections sharing a common parent