Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.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
使用SQL Server modify('insert')将数据追加到xml列_Sql_Sql Server_Xml_Xml Namespaces_Xml Dml - Fatal编程技术网

使用SQL Server modify('insert')将数据追加到xml列

使用SQL Server modify('insert')将数据追加到xml列,sql,sql-server,xml,xml-namespaces,xml-dml,Sql,Sql Server,Xml,Xml Namespaces,Xml Dml,考虑以下情况。我有下表 CREATE TABLE [dbo].[GoldenEgg] ( rowIndex int NOT NULL IDENTITY(1,1), AccountNumber varchar(256) NULL, SubscriptionID int NOT NULL, SubscriptionData_XML xml NULL, SubscriptionData_AFT

考虑以下情况。我有下表

CREATE TABLE [dbo].[GoldenEgg]
(       
    rowIndex int NOT NULL IDENTITY(1,1),    
    AccountNumber varchar(256) NULL,            
    SubscriptionID int NOT NULL,            
    SubscriptionData_XML xml NULL,
    SubscriptionData_AFTER_XML NULL     

    CONSTRAINT [PK_GoldenEgg] 
        PRIMARY KEY CLUSTERED ([rowIndex] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GoldenEgg样本数据:

SubscriptionData_SubscriptionID 6070的XML数据:

<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>
<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem>41447395</ValueItem>
      <ValueItem>56936495</ValueItem>
      <ValueItem>70660044</ValueItem>
    </Value>
  </Item>
</NVPList>
我想将每个SubscriptionID的所有帐号附加到SubscriptionData_xml列中已经存在的xml节点,我不想添加xml中已经存在的帐号

因此,对于SubscriptionID 6070,应在xml中仅列出一次账号39448474,如下所示:

<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem>56936495</ValueItem>
      <ValueItem>70660044</ValueItem>
      <ValueItem>41447395</ValueItem>    
    </Value>
  </Item>
</NVPList>

我能够通过使用XMLMODIFY方法的SQLUPDATE语句完成这项任务,而不使用任何循环。以下是解决方案的细分:

1我必须获取SubscriptionID的所有帐号,并将其格式化 转换为xml节点

SQL查询1:

SQL查询1结果:

SQL查询1 XML结果订阅ID 6070:

<ValueItem>39448474</ValueItem>
<ValueItem>41447395</ValueItem>
<ValueItem>56936495</ValueItem>
<ValueItem>70660044</ValueItem>
SQL查询2结果:

SQL查询2 XML结果SubscriptionID 6070 SubscriptionData\u AFTER\u XML列:

<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem xmlns="">39448474</ValueItem>
      <ValueItem xmlns="">41447395</ValueItem>
      <ValueItem xmlns="">56936495</ValueItem>
      <ValueItem xmlns="">70660044</ValueItem>
    </Value>
  </Item>
</NVPList> 
SQL查询3结果:

现在把所有这些放在一起,得到正确的最终结果

SQL查询4:

SQL查询4 XML结果SubscriptionID 6070 SubscriptionData\u AFTER\u XML列:

如您所见,AccountNumber 39448474现在在xml中只列出一次

<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem xmlns="">41447395</ValueItem>
      <ValueItem xmlns="">56936495</ValueItem>
      <ValueItem xmlns="">70660044</ValueItem>
    </Value>
  </Item>
</NVPList>
SQL查询5 XML结果订阅ID 6070:

<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>
<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem>41447395</ValueItem>
      <ValueItem>56936495</ValueItem>
      <ValueItem>70660044</ValueItem>
    </Value>
  </Item>
</NVPList>

我希望这能帮助那些可能需要做类似事情的人,如果XML中没有其他节点,您可以选择

一些提示:

首先,我创建一个模型表并用数据填充它 我使用可更新的CTE来收集数据 我使用不带名称空间的FOR XML子选择来构建节点,而不必担心实际XML中已经存在的ID 我使用FLWOR查询从刚刚创建的值节点构建完整的XML 由于这个CTE是可更新的,我可以直接使用它进行更新 最后一个SELECT*FROM@tbl向您显示,填充完XML之后的所有内容 试试这个:

DECLARE @tbl TABLE(rowIndex INT IDENTITY,AccountNumber INT,SubscriptionID INT, SubscriptionData_XML XML,SubscriptionData_AFTER_XML XML);
INSERT INTO @tbl VALUES
 (1111,6070,N'<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>',NULL)
,(2222,6070,NULL,NULL)
,(3333,6070,NULL,NULL)
,(4444,6070,NULL,NULL)
,(5555,6071,N'<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>',NULL)
,(6666,6071,NULL,NULL)
,(7777,6071,NULL,NULL)
,(8888,6071,NULL,NULL);
-选择以检查是否成功

SELECT * FROM @tbl

如果您还希望通过某种方式抑制嵌套for xml语句中的命名空间属性,而不必诉诸字符串操作,请更新以下Microsoft Connect项:。当我写这篇文章时,是为了接受我自己的答案,因为这是我已经实现的解决方案。您必须等待48小时才能在stackoverflow上执行此操作。您的解决方案非常好,而且使用您的解决方案,您基本上是在用帐号1111222233334444重写xml,这将替换现有的值39448474。我想保留所有原始的ValueItem's@iambdot那太好了!你有责任接受你最喜欢的答案。。。快乐编码!
<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>
      <ValueItem>41447395</ValueItem>
      <ValueItem>56936495</ValueItem>
      <ValueItem>70660044</ValueItem>
    </Value>
  </Item>
</NVPList>
DECLARE @tbl TABLE(rowIndex INT IDENTITY,AccountNumber INT,SubscriptionID INT, SubscriptionData_XML XML,SubscriptionData_AFTER_XML XML);
INSERT INTO @tbl VALUES
 (1111,6070,N'<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>',NULL)
,(2222,6070,NULL,NULL)
,(3333,6070,NULL,NULL)
,(4444,6070,NULL,NULL)
,(5555,6071,N'<NVPList xmlns="http://www.whatevernamspace.com/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Item>
    <Name>AccountNumbers</Name>
    <Value>
      <ValueItem>39448474</ValueItem>     
    </Value>
  </Item>
</NVPList>',NULL)
,(6666,6071,NULL,NULL)
,(7777,6071,NULL,NULL)
,(8888,6071,NULL,NULL);
WITH UpdateableCTE AS
(
    SELECT t1.rowIndex
          ,t1.SubscriptionData_AFTER_XML
          ,(
            SELECT t2.AccountNumber AS ValueItem
            FROM @tbl AS t2
            WHERE t2.SubscriptionID=t1.SubscriptionID
            FOR XML PATH(''),ROOT('Value'),TYPE
           ).query
                (N'declare default element namespace "http://www.whatevernamspace.com/v1";
                   let $nd:=/*:Value
                   return
                   <NVPList>
                       <Item>
                          <Name>{sql:column("XmlName")}</Name>
                          <Value>
                           {
                           for $vi in $nd/*:ValueItem
                           return <ValueItem>{$vi/text()}</ValueItem>
                           }
                          </Value>
                       </Item>
                   </NVPList>
                  '
                ) AS NewXML

    FROM @tbl AS t1
    CROSS APPLY( SELECT t1.SubscriptionData_XML.value('(//*:Name)[1]','nvarchar(max)') AS XmlName) AS x
    WHERE SubscriptionData_XML IS NOT NULL
)
UPDATE UpdateableCTE SET SubscriptionData_AFTER_XML=NewXML
FROM UpdateableCTE;
SELECT * FROM @tbl