【问题标题】:Update data in the table using XML string使用 XML 字符串更新表中的数据
【发布时间】:2011-09-13 08:21:15
【问题描述】:

我有一个表,其中包含像

这样的列
  • SiteID (identity_Col)
  • SiteName
  • POrderID
  • Location
  • Address
  • Cluster
  • VenderName

我想使用 xml 字符串在此表中插入/更新/删除数据。除了这一列,XML 字符串还包含一列,即。行信息。此列将具有“未更改”、“更新”、“新建”、“删除”等值。基于此值,应插入、更新、删除表中的行。

我的 XML 字符串如下:

<NewDataSet>
  <DataTable>
     <SiteID>2</SiteID>
     <SiteName>NIZAMPURA</SiteName>
     <POrderID>7</POrderID>
     <Location>NIZAMPURA</Location>
     <SiteAddress>Vadodara</SiteAddress>
     <Cluster>002</Cluster>
     <SubVendorName>Test Vender-1</SubVendorName>
     <RowInfo>UNCHANGED</RowInfo>
  </DataTable>
  <DataTable>
     <SiteID>16</SiteID>
     <SiteName>Site-1</SiteName>
     <POrderID>7</POrderID>
     <Location>Alkapuri</Location>
     <SiteAddress>test</SiteAddress>
     <Cluster>Test Cluster</Cluster>
     <SubVendorName>Test Vender12</SubVendorName>
     <RowInfo>UNCHANGED</RowInfo>
  </DataTable>
  <DataTable>
     <SiteID>17</SiteID>
     <SiteName>Site-3</SiteName>
     <POrderID>7</POrderID>
     <Location>Alkapuri123</Location>
     <SiteAddress>test123</SiteAddress>
     <Cluster>Test Cluster123</Cluster>
     <SubVendorName>Test Vender123</SubVendorName>
     <RowInfo>DELETE</RowInfo>
  </DataTable>
</NewDataSet>'

这是我编写的用于在 RowInfo = "NEW" 时在表中插入数据的代码

IF len(ISNULL(@xmlString, '')) > 0
    BEGIN
    DECLARE @docHandle1 int = 0;
    EXEC sp_xml_preparedocument @docHandle1 OUTPUT, @xmlString

    INSERT INTO [SiteTRS] (
                [SiteName],
                [POrderID],
                [Location],
                [SiteAddress],
                [Cluster],
                [SubVendorName])
    SELECT SiteName,POrderID,Location,SiteAddress,Cluster,SubVendorName
        FROM OPENXML (@docHandle1, '/NewDataSet/DataTable')

        WITH (SiteName varchar(50) './SiteName',
          POrderID varchar(50) './PorderID',
          Location varchar(50) './Location',
          SiteAddress varchar(max) './SiteAddress',
          Cluster varchar(50) './Cluster',
          SubVendorName varchar(50) './SubVendorName',
          RowInfo varchar(30) './RowInfo')   
    WHERE RowInfo='NEW' 

但我不知道如何使用 XML 来更新/删除表中的记录。请指导 我是 XML 的新手,所以不知道。如果我做一些幼稚的事情,请原谅我。

【问题讨论】:

    标签: sql-server xml sql-server-2008


    【解决方案1】:

    我强烈建议不要再使用旧的、遗留的 OPENXML 东西 - SQL Server 支持 XML,使用内置的 XPath/XQuery 方法要容易得多。

    在您的情况下,我会使用 CTE(通用表表达式)将 XML 分解为行和列的“内联”表:

    DECLARE @input XML = '<NewDataSet>
      <DataTable>
        <SiteID>2</SiteID>
        <SiteName>NIZAMPURA</SiteName>
        <POrderID>7</POrderID>
        <Location>NIZAMPURA</Location>
        <SiteAddress>Vadodara</SiteAddress>
        <Cluster>002</Cluster>
        <SubVendorName>Vender-1</SubVendorName>
        <RowInfo>UPDATE</RowInfo>
      </DataTable>
      <DataTable>
        <SiteName>Site-1</SiteName>
        <POrderID>7</POrderID>
        <Location>Alkapuri</Location>
        <SiteAddress>test</SiteAddress>
        <Cluster>Cluster-1</Cluster>
        <SubVendorName>Test Vender</SubVendorName>
        <RowInfo>NEW</RowInfo>
      </DataTable>
    </NewDataSet>'
    
    ;WITH XMLData AS
    (
        SELECT
            NDS.DT.value('(SiteID)[1]', 'int') AS 'SiteID',
            NDS.DT.value('(SiteName)[1]', 'varchar(50)') AS 'SiteName',
            NDS.DT.value('(POrderID)[1]', 'int') AS 'POrderID',
            NDS.DT.value('(Location)[1]', 'varchar(100)') AS 'Location',
            NDS.DT.value('(SiteAddress)[1]', 'varchar(100)') AS 'SiteAddress',
            NDS.DT.value('(Cluster)[1]', 'varchar(100)') AS 'Cluster',
            NDS.DT.value('(SubVendorName)[1]', 'varchar(100)') AS 'SubVendorName',
            NDS.DT.value('(RowInfo)[1]', 'varchar(20)') AS 'RowInfo'
        FROM 
            @input.nodes('/NewDataSet/DataTable') AS NDS(DT)
    )
    SELECT *
    FROM XMLDATA
    

    这为您提供了可以使用的行和列。

    SiteID  SiteName   POrderID Location   SiteAddress  Cluster    SubVendorName   RowInfo
      2     NIZAMPURA     7     NIZAMPURA  Vadodara     002        Vender-1        UPDATE
     NULL   Site-1        7     Alkapuri   test         Cluster-1  Test Vender     NEW
    

    现在,如果您使用的是 SQL Server 2008 或更新版本,则基本上可以将它与 MERGE command 结合起来,在一条语句中完成您的 INSERT/UPDATE

    如果您使用的是 2005,则需要将此信息存储到存储过程中的临时表/表变量中,或者您需要多次执行选择; CTE 只允许一个命令跟随它。

    更新:使用此 CTE,您可以将其与 MERGE 结合使用:

    ;WITH XmlData AS 
    (
        SELECT
            NDS.DT.value('(SiteID)[1]', 'int') AS 'SiteID',
            NDS.DT.value('(SiteName)[1]', 'varchar(50)') AS 'SiteName',
            NDS.DT.value('(POrderID)[1]', 'int') AS 'POrderID',
            NDS.DT.value('(Location)[1]', 'varchar(100)') AS 'Location',
            NDS.DT.value('(SiteAddress)[1]', 'varchar(100)') AS 'SiteAddress',
            NDS.DT.value('(Cluster)[1]', 'varchar(100)') AS 'Cluster',
            NDS.DT.value('(SubVendorName)[1]', 'varchar(100)') AS 'SubVendorName',
            NDS.DT.value('(RowInfo)[1]', 'varchar(20)') AS 'RowInfo'
        FROM 
            @input.nodes('/NewDataSet/DataTable') AS NDS(DT)
    )
    MERGE INTO dbo.SiteTRS t
    USING XmlData x ON t.SiteID = x.SiteID
    WHEN MATCHED AND x.RowInfo = 'UPDATE'
       THEN 
         UPDATE SET 
            t.SiteName = x.SiteName,
            t.POrderID = x.POrderID,
            t.Location = x.Location,
            t.SiteAddress = x.SiteAddress,
            t.Cluster = x.Cluster,
            t.SubVendorName = x.SubVendorName
    
    WHEN MATCHED AND x.RowInfo = 'DELETE'
       THEN DELETE 
    
    WHEN NOT MATCHED AND x.RowInfo = 'NEW'
       THEN 
          INSERT(SiteID, SiteName, POrderID, Location, SiteAddress, Cluster, SubVendorName)
          VALUES(x.SiteID, x.SiteName, x.POrderID, x.Location, x.SiteAddress, x.Cluster, x.SubVendorName)
    ;
    

    查看更多资源:

    【讨论】:

    • @marc_s..您提供的 MERGE 命令链接仅显示每个块中的两个操作。但我想要所有三个,即插入/更新/删除。更重要的是它显示了使用简单查询而不使用 XML 的插入/更新/删除。你能详细说明你的答案吗???
    • @Chirag Fanse:这些只是样本!当然你可以有更多个条件来定义插入、更新、删除和其他语句。浏览网页,在 Google 上搜索 - 您会发现大量信息!我用你需要做的粗略框架更新了我的答案......
    • @marc_s..更新前您的答案中的“NDS.DT.value”是什么?我认为它是 '/NewDataSet/DataTable' 的别名,因为您已经编写了“FROM @input.nodes('/NewDataSet/DataTable') AS NDS(DT)”,但是当我复制粘贴时,它显示错误“找不到列 NDS 或用户定义函数或聚合函数 NDS.DT.VALUE 或名称不明确”
    • @marc_s..我尝试了很多东西,阅读了您的链接,但仍然无法理解如何使用 XMLsting 编写插入/更新/删除命令。你能根据我的数据提供代码吗???
    • @chirag fanse:更新了我的答案再次 - 按原样输入所有陈述。 MERGE 语句将为每一行执行这些语句之一,假设 SiteID 是唯一标识每一行的唯一 ID(主键)。由于它对源表中的每一行(基于 XML 的 CTE)执行此操作,因此它知道正在执行该命令的哪一行(以及因此哪个 SiteID)——这就是为什么你可以例如如果某个条件匹配,只写... THEN DELETE - SQL Server 将知道从源表中删除哪一行
    猜你喜欢
    • 1970-01-01
    • 2018-12-25
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2012-12-14
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多