Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在SQLServer2008中合并2个XML变量_Xml_Sql Server 2008_Tsql_Xquery - Fatal编程技术网

如何在SQLServer2008中合并2个XML变量

如何在SQLServer2008中合并2个XML变量,xml,sql-server-2008,tsql,xquery,Xml,Sql Server 2008,Tsql,Xquery,假设在SQLServer2008中有2个XML变量,其中包含以下XML DECLARE @FIRST XML = '<DBPerson> <firstname>John</firstname> <lastname>Bob</lastname> </DBPerson>',

假设在SQLServer2008中有2个XML变量,其中包含以下XML

DECLARE @FIRST XML = '<DBPerson>
                          <firstname>John</firstname>
                          <lastname>Bob</lastname>
                      </DBPerson>',
        @Second XML = '<FromUI>
                           <lastname>New Bob</lastname>
                           <age>39</age>
                       </FromUI>';
但我不知道如何从这里开始。我知道我必须在某个地方使用sql:column来构建一个表,首先根据AllFields只获取节点名称及其值,然后我可以使用XML路径'DBPerson'来形成最终的XML,但有点不确定sql:column的用法

非常感谢您的帮助

更新: 我将其归结为以下问题:

DECLARE @FIRST XML = '<DBPerson><firstname>John</firstname><lastname>Bob</lastname></DBPerson>',
        @Second XML = '<FromUI><lastname>New Bob</lastname><age>39</age></FromUI>';


WITH ALLFields AS
(
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @Second.nodes('FromUI/*') AS x(y)
    UNION
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @FIRST.nodes('DBPerson/*') AS x(y)
), Filtered AS
(
    SELECT 
          Element
        , @FIRST.value('(DBPerson/*[local-name()=sql:column("Element")])[1]','varchar(max)') AS F
        , @Second.value('(FromUI/*[local-name()=sql:column("Element")])[1]','varchar(max)') AS S
    FROM ALLFields AF
), FinalValues AS
(
    SELECT
        Element 
        , CASE 
                WHEN S IS NULL THEN F
                ELSE S
            END AS V
    FROM Filtered
)
SELECT * FROM FinalValues
这个查询为我提供了一个表,其中包含一列中的所有元素以及另一列中元素的数据。现在,我如何生成最终的XML,如下所示:

WITH ALLFields AS
(
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @Second.nodes('FromUI/*') AS x(y)
    UNION
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @FIRST.nodes('DBPerson/*') AS x(y)
)
SELECT * FROM ALLFields AF
<DBPerson><firstname>John</firstname><lastname>New Bob</lastname><age>39</age></DBPerson>

比我更了解XML分解的人可能能够在XML分解级别解决这个问题,但在这里,我将对更新的查询执行动态透视。首先,我将把finalvalue写入一个staging表,以便动态SQL可以访问它:

DECLARE @FIRST XML = '<DBPerson><firstname>John</firstname><lastname>Bob</lastname></DBPerson>',
        @Second XML = '<FromUI><lastname>New Bob</lastname><age>39</age></FromUI>';


WITH ALLFields AS
(
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @Second.nodes('FromUI/*') AS x(y)
    UNION
    SELECT 
          x.y.value('local-name(.)','varchar(50)') As Element   
    FROM @FIRST.nodes('DBPerson/*') AS x(y)
), Filtered AS
(
    SELECT 
          Element
        , @FIRST.value('(DBPerson/*[local-name()=sql:column("Element")])[1]','varchar(max)') AS F
        , @Second.value('(FromUI/*[local-name()=sql:column("Element")])[1]','varchar(max)') AS S
    FROM ALLFields AF
), FinalValues AS
(
    SELECT
        Element 
        , CASE 
                WHEN S IS NULL THEN F
                ELSE S
            END AS V
    FROM Filtered
)
SELECT [age],[firstname],[lastname] FROM
    FinalValues
PIVOT (
    MAX(V)
    FOR Element IN ([age],[firstname],[lastname])
) AS p
FOR XML PATH('DBPerson');

/* Commenting out the dynamic piece to show the straight pivot above
SELECT *
INTO FinalValues_Staging
FROM FinalValues;
GO

DECLARE @sql NVARCHAR(MAX)
, @col NVARCHAR(MAX);

SELECT @col = COALESCE(@col, '') + QUOTENAME(Element) + ',' 
FROM
(
         SELECT DISTINCT Element
         FROM FinalValues_Staging
) AS x;  
SET @col = LEFT(@col, LEN(@col)-1);
SET @sql = N'SELECT <COL> FROM
    dbo.FinalValues_Staging
PIVOT (
    MAX(V)
    FOR Element IN (<COL>)
) AS p
FOR XML PATH(''DBPerson'')';

SET @sql = REPLACE(@sql, '<COL>', @col); 
EXEC sp_executeSQL @sql;
PRINT @sql;  
GO

-- DROP TABLE FinalValues_Staging
*/
结果:

<DBPerson>
  <age>39</age>
  <firstname>John</firstname>
  <lastname>New Bob</lastname>
</DBPerson>

可以使用XQuery返回序列的第一个元素,例如

DECLARE @first XML = '<DBPerson> 
                          <firstname>John</firstname> 
                          <lastname>Bob</lastname> 
                      </DBPerson>', 
        @second XML = '<FromUI> 
                           <lastname>New Bob</lastname> 
                           <age>39</age> 
                       </FromUI>'; 

DECLARE @xml XML

-- Combine the two XMLs
SET @xml = ( SELECT @first AS "*", @second AS "*" FOR XML PATH(''))

SELECT @xml.query('<DBPerson>
  {(FromUI/firstname, DBPerson/firstname)[1]}
  {(FromUI/lastname, DBPerson/lastname)[1]}
  {(FromUI/age, DBPerson/age)[1]}
</DBPerson>
')

我们不需要使用动态SQL字符串生成吗?我打算将返回的xml保存在同一存储过程中的xml变量中,并用该xml更新数据库中的一列。是的,您只需用pivot查询替换最终查询,如我的编辑中所示。同样的结果,只是硬编码的列。但是没有特定的节点列表,如firstname、lastname、age等。。我的意思是带有2个xml的节点名称是动态的。
select isnull(S.N.query('.'),F.N.query('.')) as '*'
from @First.nodes('/DBPerson/*') as F(N)
  full outer join @Second.nodes('/FromUI/*') as S(N)
    on F.N.value('local-name(.)', 'nvarchar(100)') = S.N.value('local-name(.)', 'nvarchar(100)')
for xml path(''), root('DBPerson')
DECLARE @first XML = '<DBPerson> 
                          <firstname>John</firstname> 
                          <lastname>Bob</lastname> 
                      </DBPerson>', 
        @second XML = '<FromUI> 
                           <lastname>New Bob</lastname> 
                           <age>39</age> 
                       </FromUI>'; 

DECLARE @xml XML

-- Combine the two XMLs
SET @xml = ( SELECT @first AS "*", @second AS "*" FOR XML PATH(''))

SELECT @xml.query('<DBPerson>
  {(FromUI/firstname, DBPerson/firstname)[1]}
  {(FromUI/lastname, DBPerson/lastname)[1]}
  {(FromUI/age, DBPerson/age)[1]}
</DBPerson>
')