【问题标题】:Query Optimization while updating XML String in SQL Server?在 SQL Server 中更新 XML 字符串时的查询优化?
【发布时间】:2017-06-02 12:26:34
【问题描述】:

我正在使用如下所示的 XML 字符串。

我必须按如下方式更新 XML 字符串:

  • 如果 XML 字符串包含 1000 条或更多记录,则会终止查询
  • 如果 XML 字符串包含

我该怎么做?

示例数据

<root xmlns:json="http://james.newtonking.com/projects/json">
  <row json:Array="true" RowNumber="1">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.2" />
    <Column json:Array="true" Name="HourTo" Value="13.3" />
    <Column json:Array="true" Name="Rate" Value="0.895" />
  </row>
  <row json:Array="true" RowNumber="2">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.3" />
    <Column json:Array="true" Name="HourTo" Value="13.4" />
    <Column json:Array="true" Name="Rate" Value="0.907" />
  </row>
</root>

创建临时表

    CREATE TABLE #xmltable(
                           Id INT Identity (1,1)  PRIMARY KEY CLUSTERED,
                           DataValue XML
                          );


    CREATE PRIMARY XML INDEX indexratesheet ON #xmltable
                    (
                      DataValue 
                     ) 

向表格中插入数据

    INSERT INTO (DataValue ) VALUES(TheXMLfromAbove)

更新表格中的 XML 字符串

    DECLARE @i INT 1
    WHILE(@i<=1000)
    BEGIN
         UPDATE #xmltable SET DataValue.modify('insert <Column Name="ValidationComments" Value="{sql:variable("@validationcomments")}"></Column>
                              into (/root/row[@i=sql:variable("@i")])[1]')
   SET @i=@i+1
   END

【问题讨论】:

  • 这个数据看起来很像 better-to-store-in-a-table,不是吗?是否有充分的理由将其保留在 XML 中?我会将其存储在普通表中,并在需要时创建 XML...
  • 这个问题解决了吗?您需要进一步的帮助吗?请给我一个提示:如果这个问题得到了解决,您将非常好心,在(最佳)答案的投票计数器下方勾选接受检查。这将 1) 将此问题标记为已解决 2) 让追随者更容易找到最佳解决方案 3) 向回答者支付积分和 4) 向您支付积分。由于您自己已经越过了 15 点边界,因此您还被要求对贡献进行投票。这是说谢谢的方式。快乐编码!

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


【解决方案1】:

如果您必须使用 XML 保留它,那么将整个 XML 分解成一个derivedTable 并从头开始重新构建它应该会更快。

试试这个:

CREATE TABLE #xmltable(
                           Id INT Identity (1,1)  PRIMARY KEY CLUSTERED,
                           DataValue XML
                          );


    CREATE PRIMARY XML INDEX indexratesheet ON #xmltable
                    (
                      DataValue 
                     );

--你的测试 XML

    INSERT INTO #xmltable (DataValue ) VALUES(N'<root xmlns:json="http://james.newtonking.com/projects/json">
  <row json:Array="true" RowNumber="1">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.2" />
    <Column json:Array="true" Name="HourTo" Value="13.3" />
    <Column json:Array="true" Name="Rate" Value="0.895" />
  </row>
  <row json:Array="true" RowNumber="2">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.3" />
    <Column json:Array="true" Name="HourTo" Value="13.4" />
    <Column json:Array="true" Name="Rate" Value="0.907" />
  </row>
</root>');

--粉碎它的查询

SELECT r.value(N'@RowNumber','int') AS RowNumber
      ,r.value(N'(Column[@Name="Number"]/@Value)[1]','int') AS Number
      ,r.value(N'(Column[@Name="HourFrom"]/@Value)[1]','decimal(10,4)') AS HourFrom
      ,r.value(N'(Column[@Name="HourTo"]/@Value)[1]','decimal(10,4)') AS HourTo
      ,r.value(N'(Column[@Name="Rate"]/@Value)[1]','decimal(10,4)') AS Rate
INTO #derivedTable
FROM #xmltable AS t
CROSS APPLY t.DataValue.nodes(N'/root/row') AS A(r);

--重建它的查询

WITH XMLNAMESPACES('http://james.newtonking.com/projects/json' AS json)
SELECT 'true' AS [@json:Array]
      ,t.RowNumber AS [@RowNumber]
      ,'true' AS [Column/@json:Array]
      ,'Number' AS [Column/@Name]
      ,t.Number AS [Column/@Value]
      ,''
      ,'true' AS [Column/@json:Array]
      ,'HourFrom' AS [Column/@Name]
      ,t.HourFrom AS [Column/@Value]
      ,''
      ,'true' AS [Column/@json:Array]
      ,'HourTo' AS [Column/@Name]
      ,t.HourTo AS [Column/@Value]
      ,''
      ,'true' AS [Column/@json:Array]
      ,'Rate' AS [Column/@Name]
      ,t.Rate AS [Column/@Value]

      ,''
      ,'ValidationComments' AS [Column/@Name]
      ,'SomeValue' AS [Column/@Value]
FROM #derivedTable AS t
FOR XML PATH('row'),ROOT('root');

--清理(注意真实数据!)

GO

DROP TABLE #derivedTable;
DROP TABLE #xmltable

这是结果

<root xmlns:json="http://james.newtonking.com/projects/json">
  <row json:Array="true" RowNumber="1">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.2000" />
    <Column json:Array="true" Name="HourTo" Value="13.3000" />
    <Column json:Array="true" Name="Rate" Value="0.8950" />
    <Column Name="ValidationComments" Value="SomeValue" />
  </row>
  <row json:Array="true" RowNumber="2">
    <Column json:Array="true" Name="Number" Value="1" />
    <Column json:Array="true" Name="HourFrom" Value="13.3000" />
    <Column json:Array="true" Name="HourTo" Value="13.4000" />
    <Column json:Array="true" Name="Rate" Value="0.9070" />
    <Column Name="ValidationComments" Value="SomeValue" />
  </row>
</root>

更新

试试这个查询,它适用于所有不同的列列表,但它会重复命名空间声明。这没有错,但很烦人。目前我没有时间考虑黑客攻击。让我知道,如果这对你有用。

WITH XMLNAMESPACES('http://james.newtonking.com/projects/json' AS json)
,CTE AS
(
    SELECT r.value(N'@RowNumber','int') AS RowNumber
          ,r.query('./*') AS TheContent
    FROM #xmltable AS t
    CROSS APPLY t.DataValue.nodes(N'/root/row') AS A(r)
)
SELECT CTE.TheContent AS [*]
      ,'ValidationComments' AS [Column/@Name]
      ,'SomeValue' AS [Column/@Value]
FROM CTE
FOR XML PATH('row'),ROOT('root')

【讨论】:

  • 在下面的 xml 字符串中,只有根节点和行节点是静态的,行节点中的列节点是动态的,我怎样才能按照你的建议实现这一点
  • @PhaniRao 你想通过这个 XML 片段告诉我什么?
  • 请在等待您的回复后查看评论
  • @PhaniRao 我理解正确吗:&lt;root&gt;&lt;row&gt; 中的内容是动态的(不同的列)?
  • @PhaniRao 还有一个问题:json:Array="true" 真的需要吗?选择它会更容易,因为它似乎到处都是一样的(由于命名空间问题......)
猜你喜欢
  • 2018-03-12
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多