将多个存储过程的结果组合到单个XML中

时间:2016-02-27 11:34:56

标签: sql-server xml stored-procedures sql-insert

SQL Server 2014:寻找[从多个存储过程到XML的综合结果]中发布的解决方案[1] [1]:http://www.sqlservercentral.com/Forums/Topic1377879-21-1.aspx

我希望输出像

<root>
  <Products>
    <...>
  </Products>
  <Colours>
    <...>
  </Colours>
  <Sizes>
     <...>
  </Sizes>
</root>

代码:

DECLARE @TempExportTable TABLE
(
   Products XML,
   Colours XML,
   Sizes XML
)

INSERT INTO @TempExportTable VALUES
(
    EXEC ('
       EXEC [dbo].[spGetProductsDesc] @tId FOR XML AUTO, ELEMENTS;
       EXEC [dbo].[spGetColoursDesc] @tId FOR XML AUTO, ELEMENTS;
       EXEC [dbo].[spGetSizesDesc] @tId FOR XML AUTO, ELEMENTS;
   ');
)

SELECT 
   Products as '*',
   Colours as '*',
   Sizes as '*' 
from @TempExportTable 
FOR XML PATH('ExportList')

这可以实现吗?

2 个答案:

答案 0 :(得分:2)

试试这个(SP必须输出像xml数据一样的xml或nvarchar):

DECLARE @TempExportTable TABLE (Results xml);

INSERT INTO @TempExportTable
EXEC [dbo].[spGetProductsDesc] @tId;
--The output must be like:
--<Products>
--  <Product id="1" name="pr1" />
--  <Product id="2" name="pr2" />
--  ...
--</Products>

INSERT INTO @TempExportTable
EXEC [dbo].[spGetColoursDesc] @tId;
--The output must be like:
--<Colours>
--  <Colour id="1" name="red" />
--  <Colour id="2" name="white" />
--  ...
--</Colours>

INSERT INTO @TempExportTable
EXEC [dbo].[spGetSizesDesc] @tId;
--
--<Sizes>
--  <Size id="1" name="S" />
--  <Size id="2" name="M" />
--  ...
--</Sizes>

SELECT Results as '*'
FROM @TempExportTable 
for xml PATH('') ,ROOT('root');

结果:

<root>
  <Products>
    <Product id="1" name="pr1" />
    <Product id="2" name="pr2" />
    <Product id="3" name="pr3" />
  </Products>
  <Colours>
    <Colour id="1" name="red" />
    <Colour id="2" name="white" />
    <Colour id="3" name="green" />
  </Colours>
  <Sizes>
    <Size id="1" name="S" />
    <Size id="2" name="M" />
    <Size id="3" name="L" />
  </Sizes>
</root>

答案 1 :(得分:1)

您的问题是,这些SP可能会在结构上提供不同的行集。 SP不是仅仅读取数据的正确方法......不知道你在SP中做了什么,但对于TVF来说这可能会更容易

以下示例说明如何实现您的目标:

CREATE PROCEDURE dbo.Test1 
AS
BEGIN
SELECT * FROM (VALUES(1,'Test1_1'),(2,'Test1_2')) AS tbl(t1a,t1b);
END
GO
CREATE PROCEDURE dbo.Test2
AS
BEGIN
SELECT * FROM (VALUES('a','Test1_A',100),('b','Test1_B',200)) AS tbl(t2a,t2b,t2c);
END
GO
CREATE PROCEDURE dbo.Test3
AS
BEGIN
SELECT * FROM (VALUES('a'),('b')) AS tbl(t3);
END
GO

--Here starts your solution
--First we need tables to fill the SPs results into
--The column's names don't have to be the same as delivered from the SP...
DECLARE @t1 TABLE(t1x INT,t1y VARCHAR(100));
INSERT INTO @t1 EXEC dbo.Test1;

DECLARE @t2 TABLE(t1x VARCHAR(100),t2y VARCHAR(100),t3z INT);
INSERT INTO @t2 EXEC dbo.Test2;

DECLARE @t3 TABLE(t3x VARCHAR(100));
INSERT INTO @t3 EXEC dbo.Test3;

SELECT (SELECT * FROM @t1 FOR XML PATH('T1_Row'),ROOT('T1'),TYPE)
      ,(SELECT * FROM @t2 FOR XML PATH('T2_Row'),ROOT('T2'),TYPE)
      ,(SELECT * FROM @t3 FOR XML PATH('T3_Row'),ROOT('T3'),TYPE)
FOR XML PATH(''),ROOT('root')
GO

DROP PROCEDURE dbo.Test1;
DROP PROCEDURE dbo.Test2;
DROP PROCEDURE dbo.Test3;

完全相同的结果,但更容易调用的是标量函数的这种方法:

CREATE FUNCTION dbo.Test1()
RETURNS XML
AS
BEGIN
RETURN (SELECT * FROM (VALUES(1,'Test1_1'),(2,'Test1_2')) AS tbl(t1a,t1b) FOR XML PATH('T1_Row'),ROOT('T1'));
END
GO
CREATE FUNCTION dbo.Test2()
RETURNS XML
AS
BEGIN
RETURN (SELECT * FROM (VALUES('a','Test1_A',100),('b','Test1_B',200)) AS tbl(t2a,t2b,t2c) FOR XML PATH('T2_Row'),ROOT('T2'));
END
GO
CREATE FUNCTION dbo.Test3()
RETURNS XML
AS
BEGIN
RETURN (SELECT * FROM (VALUES('a'),('b')) AS tbl(t3) FOR XML PATH('T3_Row'),ROOT('T3'));
END
GO


SELECT (SELECT dbo.Test1())
      ,(SELECT dbo.Test2())
      ,(SELECT dbo.Test3())
FOR XML PATH(''),ROOT('root')
GO

DROP FUNCTION dbo.Test1;
DROP FUNCTION dbo.Test2;
DROP FUNCTION dbo.Test3;

两种情况下的结果:

<root>
  <T1>
    <T1_Row>
      <t1x>1</t1x>
      <t1y>Test1_1</t1y>
    </T1_Row>
    <T1_Row>
      <t1x>2</t1x>
      <t1y>Test1_2</t1y>
    </T1_Row>
  </T1>
  <T2>
    <T2_Row>
      <t1x>a</t1x>
      <t2y>Test1_A</t2y>
      <t3z>100</t3z>
    </T2_Row>
    <T2_Row>
      <t1x>b</t1x>
      <t2y>Test1_B</t2y>
      <t3z>200</t3z>
    </T2_Row>
  </T2>
  <T3>
    <T3_Row>
      <t3x>a</t3x>
    </T3_Row>
    <T3_Row>
      <t3x>b</t3x>
    </T3_Row>
  </T3>
</root>