【问题标题】:Combined results of multiple stored procedures to a single XML将多个存储过程的结果合并到单个 XML
【发布时间】:2016-02-27 11:34:55
【问题描述】:

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

这可以实现吗?

【问题讨论】:

  • 有什么原因,为什么你的spGet.... 例程是存储过程?如果它们是标量函数,或者——甚至更好——一个 TVF 一次返回所有 XML,那会容易得多……顺便说一句:建议不要使用像“sp”这样的前缀,尤其是保留的“sp_”。 .

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


【解决方案1】:

试试这个(SP必须输出xml或nvarchar之类的xml数据):

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>

【讨论】:

  • 您假设所有 SP 都返回 one 文本或 XML 列。你试过这个吗?如果您的表包含多个文本内容,您将获得多个没有根的 XML 节点。所有这些都被命名为“ExportList”。如果内容是预定义的 XML,你最终会得到一堆 &amp;lt;&amp;gt;&amp;lt;&amp;gt;&amp;lt;&amp;gt;&amp;lt;&amp;gt; ...
  • 好吧,当我需要将 1 列数据(例如 xml)放入 1 个表中以得到 1 个大结果时,我使用相同类型的查询。
  • 是的,但是您是否尝试将其与FOR XML PATH() 结合使用?尝试使用“裸”文本、“xml as varchar”和“真实”xml。他们都不会像 OP 想要的那样......
  • 好的,这是让它使用这种方法的唯一机会。但是 SP 必须提供一个现成的 XML(为标量函数而哭!!)并且您的临时表也必须使用“真实”的 XML。最后,您必须摆脱“ExportList”节点,并且必须添加一个根节点:-)。在这种情况下,将全部内容保留在字符串连接中可能会更简单:-)
  • 使用 SP 来读取数据是非常普遍的事情。我不知道为什么...尤其是如果您不能将结果集“交付”,如果您想对您的数据做某事,那简直是脖子疼!标量函数(在这种情况下)和更好的表值函数(但只有在没有BEGINEND 的“内联语法”)或VIEW好多了 .
【解决方案2】:

您的问题是,这些 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>

【讨论】:

  • 感谢所有回复的人。但是带有 INSERT 的 EXEC SP 不能立即工作,它需要 OPENQUERY。但是这个 OPENQUERY 似乎并没有以我必须提供给 SP 的变量的形式接受参数。上述答案之一将产生多个 xml,我只需要一个 xml 中的所有这些。我转储了 3 个 SP,并将它们合并为一个 SP 以获得结果。但替代答案是@Shnugo 建议的标量或多值函数。感谢您的尝试。
  • @TechBangalore,非常感谢您,但请允许我一些提示:1)如果您在 my 答案下方添加“感谢大家”,我将是唯一阅读此内容的人... 2)这里最好的“谢谢”是投票和接受。@ 987654321@,和3)在您的问题中,没有什么可阅读的关于OPENQUERY。如果您的问题 - 如其所写 - 已解决,您应该接受最佳答案。如果您的实际问题未解决 - 由于未提及的问题,请提出一个新问题(在评论中链接)。
  • 关于 OPENQUERY,你弄错了。我的意思是 INSERT-EXEC 不能立即工作,proc 必须在 OPENQUERY 中执行。但是很难将变量传递给 OPENQUERY。多值函数可以解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-06
  • 2011-07-14
  • 2013-08-02
  • 2019-03-07
  • 1970-01-01
  • 2012-07-19
相关资源
最近更新 更多