我怎样才能让这个 SQL 函数更快地解析 XML

How can I make this SQL function that parses XML faster

我很难找到一种方法来将此自定义 SQL 脚本改进为 Umbraco 数据库。

这是获取和解析 xml 和 select 正确值的 sql 脚本:

DECLARE @Title nvarchar(1000)
SET @Title =
(SELECT @NodeXml.query('//TechnicalData/title' ).value('.', 'nvarchar(max)') Title
FROM cmsContentXml xt JOIN umbracoNode un ON un.id = xt.NodeId
WHERE xt.nodeId = @NodeId)

SELECT iif(CHARINDEX('"values":null', @Title,0) > 0,'',Substring(@Title, 21, CHARINDEX('}', @Title) - 22)) Title

部分XML如下:

<?xml version="1.0"?>
<TechnicalData id="1261" key="b6a2f67a-0f0f-40dd-a3c6-c5fb9d8b78b9" parentID="1092" level="3" creatorID="0" sortOrder="12" createDate="2016-07-14T13:56:37" updateDate="2016-07-15T12:06:25" nodeName="Rioolkolken Type 1 Drainerend via de zijwanden" urlName="rioolkolken-type-1-drainerend-via-de-zijwanden" path="-1,1089,1092,1261" isDoc="" nodeType="1154" creatorName="admin" writerName="Karl" writerID="1" template="1085" nodeTypeAlias="TechnicalData">
    <title>{"values":{"nl-BE":"Rioolkolken Type 1 Drainerend via de zijwanden"},"dtdGuid":"f2dfa88e-63b9-4913-80cd-64d770cef90e"}</title>
</TechnicalData>

这只是脚本的一小部分。 TechnicalData 包含大约 20 个节点,所有这些节点都必须被解析。可以找到完整的脚本 here

这个自定义脚本的原因是因为我需要使用 ssrs 报告扩展 Umbraco 站点。

在单个 select

中解析所有节点
DECLARE @NodeXml xml;

-- sample data
SET @NodeXml ='<TechnicalData id="1261" key="b6a2f67a-0f0f-40dd-a3c6-c5fb9d8b78b9" parentID="1092" level="3" creatorID="0" sortOrder="12" createDate="2016-07-14T13:56:37" updateDate="2016-07-15T12:06:25" nodeName="Rioolkolken Type 1 Drainerend via de zijwanden" urlName="rioolkolken-type-1-drainerend-via-de-zijwanden" path="-1,1089,1092,1261" isDoc="" nodeType="1154" creatorName="admin" writerName="Karl" writerID="1" template="1085" nodeTypeAlias="TechnicalData">
    <title>{"values":{"nl-BE":"Rioolkolken Type 1 Drainerend via de zijwanden"},"dtdGuid":"f2dfa88e-63b9-4913-80cd-64d770cef90e"}</title>
</TechnicalData>';

DECLARE @Title nvarchar(1000);
DECLARE @Subtitle nvarchar(1000)
DECLARE @Company int;
DECLARE @Date Datetime;

SELECT @Date = @NodeXml.value('(/TechnicalData/@createDate)[1]', 'datetime')
 ,@Title = td.node.value('title[1]','nvarchar(max)')
 ,@Subtitle = td.node.value('subtitle[1]','nvarchar(max)')
 ,@Company = td.node.value('bedrijf[1]','int')
 -- and so on
FROM  @NodeXml.nodes('TechnicalData') td(node);

--check it
SELECT @Date,@Title,@Subtitle,@Company ;

你的方法很慢,因为你一遍又一遍地从 XML 中取出一点信息。

有了这个,您将一次性从 XML 中获得 所有数据类型安全 ,无需任何字符串解析。

DECLARE @NodeXml XML=
N'<?xml version="1.0"?>
<TechnicalData id="1261" key="b6a2f67a-0f0f-40dd-a3c6-c5fb9d8b78b9" parentID="1092" level="3" creatorID="0" sortOrder="12" createDate="2016-07-14T13:56:37" updateDate="2016-07-15T12:06:25" 
nodeName="Rioolkolken Type 1 Drainerend via de zijwanden" urlName="rioolkolken-type-1-drainerend-via-de-zijwanden" path="-1,1089,1092,1261" isDoc="" nodeType="1154" creatorName="admin" writerName="Karl" writerID="1" template="1085" nodeTypeAlias="TechnicalData">
    <title>{"values":{"nl-BE":"Rioolkolken Type 1 Drainerend via de zijwanden"},"dtdGuid":"f2dfa88e-63b9-4913-80cd-64d770cef90e"}</title>
</TechnicalData>';

SELECT td.value('@id','int') AS id
      ,td.value('@key','uniqueidentifier') AS [key]
      ,td.value('@parentID','int') AS parentID
      ,td.value('@level','int') AS [level]
      ,td.value('@creatorID','int') AS creatorID
      ,td.value('@sortOrder','int') AS sortOrder
      ,td.value('@createDate','datetime') AS createDate
      ,td.value('@updateDate','datetime') AS updateDate
      ,td.value('@nodeName','nvarchar(max)') AS nodeName
      ,td.value('@urlName','nvarchar(max)') AS urlName
      ,td.value('@path','nvarchar(max)') AS [path]
      ,td.value('@isDoc','nvarchar(max)') AS isDoc
      ,td.value('@nodeType','int') AS nodeType
      ,td.value('@creatorName','nvarchar(max)') AS creatorName
      ,td.value('@writerName','nvarchar(max)') AS writerName
      ,td.value('@writerID','int') AS writerID
      ,td.value('@template','int') AS template
      ,td.value('@nodeTypeAlias','nvarchar(max)') AS nodeTypeAlias

      ,td.value('title[1]','nvarchar(max)') AS Title

FROM @NodeXml.nodes('TechnicalData') AS A(td)

本例中的结果是一行,所有数据都在列中。

我怀疑,您是否需要声明变量中的值,最好将上面的值用作 CTE(基于集合/内联/临时 在大多数情况下优于 procedural) 并使用那里的值。但是:将收集到的信息填充到声明的变量中也很容易(如果确实需要的话)。在这种情况下,只需使用正确的类型声明变量并使用语法

SELECT @MyVariable=td.value('@id','int') 
      ,@OtherVariable= ...
... same for the rest...