Sql server 高效分解以元素为中心的XML TSQL

Sql server 高效分解以元素为中心的XML TSQL,sql-server,xml,performance,tsql,xquery-sql,Sql Server,Xml,Performance,Tsql,Xquery Sql,我正在尝试拆分具有多个嵌套元素级别的XML文档: <server> <name>111.111.11.11</name> <displayName>EVIL SERVER</displayName> <comment /> <logonCredentials inherit="None">

我正在尝试拆分具有多个嵌套元素级别的XML文档:

<server>
            <name>111.111.11.11</name>
            <displayName>EVIL SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user</userName>
                <domain>DOMAIN</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="None">
                <audioRedirection>2</audioRedirection>
                <audioRedirectionQuality>2</audioRedirectionQuality>
                <audioCaptureRedirection>0</audioCaptureRedirection>
                <keyboardHook>2</keyboardHook>
                <redirectClipboard>True</redirectClipboard>
                <redirectDrives>True</redirectDrives>
                <redirectPorts>False</redirectPorts>
                <redirectPrinters>False</redirectPrinters>
                <redirectSmartCards>False</redirectSmartCards>
            </localResources>
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
        <server>
            <name>111.12.11.11</name>
            <displayName>NICE SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user2</userName>
                <domain>DOMAIN2</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="FromParent" />
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
然而,我只是开始构建这个查询,很明显,它将永远无法运行


我也尝试过OPENXML,但我只能得到一个级别

我不会在Transact-SQL中这样做。虽然您可以在SQL Server中处理XML,但只有在无法在更高级别上处理XML时,您才希望在SQL Server中处理XML,因为您有更好(更快)的工具

如果我是你,我会在C#中编写一组简单的类,该类是XElement的子类,并公开一个名为StuffParameters()的方法,以方便使用insert/update语句。因为XML分解在.Net中非常简单

// Typed in the editor -- code needs to be eval'd before attempting to compile!
public class ServerData: XElement
{
    public ServerData(string strServer): base(strServer)
    {
        // Base class initializes XElement with XML, throws error if XML not well-formed
    }

    // Properties
    public string Name    // One example of the two dozen properties you'll need
    {
        get()
        {
            return GetAttribute("name");
        }
    }

    // StuffParameters
    public bool StuffParameters(SqlCommand objCommand)
    {
        // In real life you'd use try...catch, but this is prototype code, right?
        objCommand.Parameters["@ServerName"].Value = Name;
        // ... and so forth
    }
}
从服务器XDocuments列表开始;为每个类创建该类的实例。创建到数据库的连接,并使用存储过程创建SqlCommand对象。迭代这些类的列表,将命令传递给每个类实例的StuffParameters()方法

当函数返回时,对命令调用ExecuteNonQuery(),您就已经将记录插入到表中了

更少的编码,更正统的处理XML的方法——因此,如果您不得不更改它,您不会得到一个需要花费数小时思考的令人头痛的方法


希望这对您有所帮助……

这实际上比您预期的要简单得多。通过使用单个
.nodes()
函数,然后在
.value()
函数中指定子路径,可以轻松地遍历XML:

SELECT n.value('(./name/text())[1]','varchar(15)') AS [name],
       n.value('(./displayName/text())[1]','varchar(15)') AS [displayName],
       n.value('(./comment/text())[1]','varchar(15)') AS [comment],
  n.value('(./logonCredentials/userName/text())[1]','varchar(15)') AS [userName],
      n.value('(./logonCredentials/domain/text())[1]','varchar(15)') AS [domain],
  n.value('(./logonCredentials/password/text())[1]','varchar(15)') AS [password],
       n.value('(./connectionSettings/text())[1]','varchar(15)')
              AS [connectionSettings],
     n.value('(./gatewaySettings/text())[1]','varchar(15)') AS [gatewaySettings],
       n.value('(./remoteDesktop/text())[1]','varchar(15)') AS [remoteDesktop],
       n.value('(./localResources/audioRedirection/text())[1]','varchar(15)')
              AS [audioRedirection],
    n.value('(./localResources/audioRedirectionQuality/text())[1]','varchar(15)')
              AS [audioRedirectionQuality],
    n.value('(./localResources/audioCaptureRedirection/text())[1]','varchar(15)')
              AS [audioCaptureRedirection],
   n.value('(./securitySettings/text())[1]','varchar(15)') AS [securitySettings],
      n.value('(./displaySettings/text())[1]','varchar(15)') AS [displaySettings]
FROM @RDCM.nodes('/group/server') AS s(n)
全面测试:

DECLARE @RDCM XML
SET @RDCM = N'<group>
<server>
            <name>111.111.11.11</name>
            <displayName>EVIL SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user</userName>
                <domain>DOMAIN</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="None">
                <audioRedirection>2</audioRedirection>
                <audioRedirectionQuality>2</audioRedirectionQuality>
                <audioCaptureRedirection>0</audioCaptureRedirection>
                <keyboardHook>2</keyboardHook>
                <redirectClipboard>True</redirectClipboard>
                <redirectDrives>True</redirectDrives>
                <redirectPorts>False</redirectPorts>
                <redirectPrinters>False</redirectPrinters>
                <redirectSmartCards>False</redirectSmartCards>
            </localResources>
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
        <server>
            <name>111.12.11.11</name>
            <displayName>NICE SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user2</userName>
                <domain>DOMAIN2</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="FromParent" />
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
        </group>'


SELECT n.value('(./name/text())[1]','varchar(15)') AS [name],
       n.value('(./displayName/text())[1]','varchar(15)') AS [displayName],
       n.value('(./comment/text())[1]','varchar(15)') AS [comment],
n.value('(./logonCredentials/userName/text())[1]','varchar(15)') AS [userName],
    n.value('(./logonCredentials/domain/text())[1]','varchar(15)') AS [domain],
n.value('(./logonCredentials/password/text())[1]','varchar(15)') AS [password],
       n.value('(./connectionSettings/text())[1]','varchar(15)')
              AS [connectionSettings],
   n.value('(./gatewaySettings/text())[1]','varchar(15)') AS [gatewaySettings],
       n.value('(./remoteDesktop/text())[1]','varchar(15)') AS [remoteDesktop],
       n.value('(./localResources/audioRedirection/text())[1]','varchar(15)')
              AS [audioRedirection],
  n.value('(./localResources/audioRedirectionQuality/text())[1]','varchar(15)')
              AS [audioRedirectionQuality],
  n.value('(./localResources/audioCaptureRedirection/text())[1]','varchar(15)')
              AS [audioCaptureRedirection],
 n.value('(./securitySettings/text())[1]','varchar(15)') AS [securitySettings],
    n.value('(./displaySettings/text())[1]','varchar(15)') AS [displaySettings]
FROM @RDCM.nodes('/group/server') AS s(n)
DECLARE@RDCM-XML
设置为@RDCM=N'
111.111.11.11
邪恶服务器
使用者
领域
xxxxxxx
2.
2.
0
2.
符合事实的
符合事实的
错误的
错误的
错误的
111.12.11.11
好服务器
用户2
域2
xxxxxxx
'
选择n.value(“(./name/text())[1]”,'varchar(15)”作为[name],
n、 值(“(./displayName/text())[1]”,'varchar(15)”作为[displayName],
n、 值(“(./comment/text())[1]”,'varchar(15)”作为[comment],
n、 值(“(./logonCredentials/userName/text())[1]”,'varchar(15)”作为[userName],
n、 值(“(./logonCredentials/domain/text())[1]”,'varchar(15)”作为[domain],
n、 值(“(./logonCredentials/password/text())[1]”,'varchar(15)”作为[password],
n、 值('(./connectionSettings/text())[1]','varchar(15)'
作为[连接设置],
n、 值(“(./gatewaySettings/text())[1]”,“varchar(15)”作为[gatewaySettings],
n、 值(“(./remoteDesktop/text())[1]”,'varchar(15)”作为[remoteDesktop],
n、 值('(./localResources/audioRedirection/text())[1],'varchar(15)'
作为[音频重定向],
n、 值(“(./localResources/audioRedirectionQuality/text())[1]”,'varchar(15)'
作为[音频重定向质量],
n、 值(“(./localResources/audioCaptureRedirection/text())[1]”,'varchar(15)'
作为[音频捕获重定向],
n、 值(“(./securitySettings/text())[1]”,“varchar(15)”作为[securitySettings],
n、 值(“(./displaySettings/text())[1]”,“varchar(15)”作为[displaySettings]
将@RDCM.nodes('/group/server')作为s(n)从

永远是一段很长的时间。您的XML有多大?您必须解析多少个服务器节点?需要多长时间?而且看起来你根本不需要交叉申请。在values()函数中使用路径表达式完全可以。openxml也是如此。您正在服务器上分解,其余的只是为了找到您需要的值。
DECLARE @RDCM XML
SET @RDCM = N'<group>
<server>
            <name>111.111.11.11</name>
            <displayName>EVIL SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user</userName>
                <domain>DOMAIN</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="None">
                <audioRedirection>2</audioRedirection>
                <audioRedirectionQuality>2</audioRedirectionQuality>
                <audioCaptureRedirection>0</audioCaptureRedirection>
                <keyboardHook>2</keyboardHook>
                <redirectClipboard>True</redirectClipboard>
                <redirectDrives>True</redirectDrives>
                <redirectPorts>False</redirectPorts>
                <redirectPrinters>False</redirectPrinters>
                <redirectSmartCards>False</redirectSmartCards>
            </localResources>
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
        <server>
            <name>111.12.11.11</name>
            <displayName>NICE SERVER</displayName>
            <comment />
            <logonCredentials inherit="None">
                <userName>user2</userName>
                <domain>DOMAIN2</domain>
                <password storeAsClearText="True">xxxxxxx</password>
            </logonCredentials>
            <connectionSettings inherit="FromParent" />
            <gatewaySettings inherit="FromParent" />
            <remoteDesktop inherit="FromParent" />
            <localResources inherit="FromParent" />
            <securitySettings inherit="FromParent" />
            <displaySettings inherit="FromParent" />
        </server>
        </group>'


SELECT n.value('(./name/text())[1]','varchar(15)') AS [name],
       n.value('(./displayName/text())[1]','varchar(15)') AS [displayName],
       n.value('(./comment/text())[1]','varchar(15)') AS [comment],
n.value('(./logonCredentials/userName/text())[1]','varchar(15)') AS [userName],
    n.value('(./logonCredentials/domain/text())[1]','varchar(15)') AS [domain],
n.value('(./logonCredentials/password/text())[1]','varchar(15)') AS [password],
       n.value('(./connectionSettings/text())[1]','varchar(15)')
              AS [connectionSettings],
   n.value('(./gatewaySettings/text())[1]','varchar(15)') AS [gatewaySettings],
       n.value('(./remoteDesktop/text())[1]','varchar(15)') AS [remoteDesktop],
       n.value('(./localResources/audioRedirection/text())[1]','varchar(15)')
              AS [audioRedirection],
  n.value('(./localResources/audioRedirectionQuality/text())[1]','varchar(15)')
              AS [audioRedirectionQuality],
  n.value('(./localResources/audioCaptureRedirection/text())[1]','varchar(15)')
              AS [audioCaptureRedirection],
 n.value('(./securitySettings/text())[1]','varchar(15)') AS [securitySettings],
    n.value('(./displaySettings/text())[1]','varchar(15)') AS [displaySettings]
FROM @RDCM.nodes('/group/server') AS s(n)