0

我在 SQL 中查询扩展事件的系统表以获取有关扩展事件本身的一些数据,并且我想获取在创建扩展事件时设置的数据库。

如果我在这里从系统表运行此查询:

SELECT SESE.predicate_xml
FROM sys.server_event_sessions SEV
LEFT OUTER JOIN sys.server_event_session_fields SESF ON SEV.event_session_id = SESF.event_session_id
LEFT OUTER JOIN sys.server_event_session_events SESE ON SEV.event_session_id = SESE.event_session_id

我可以得到 predicate_XML 的 XML 字符串,它为我提供类似于以下的 XML:

<and>
  <and>
    <or>
      <leaf>
        <comparator name="equal_uint64" package="package0" />
        <event name="sp_statement_starting" package="sqlserver" field="object_type" />
        <value>8272</value>
      </leaf>
      <leaf>
        <comparator name="equal_uint64" package="package0" />
        <event name="sp_statement_starting" package="sqlserver" field="object_type" />
        <value>20038</value>
      </leaf>
    </or>
    <leaf>
      <comparator name="equal_i_sql_unicode_string" package="sqlserver" />
      <global name="database_name" package="sqlserver" />
      <value>DatabasenameHere</value>
    </leaf>
  </and>
  <leaf>
    <comparator name="equal_boolean" package="package0" />
    <global name="is_system" package="sqlserver" />
    <value>false</value>
  </leaf>
</and>

database_name 有一个 XML,我想获取它的值。

这是一个非常简单的扩展事件,因此有一个非常小的 XML,但它可能会变得很大,并且可以有多个数据库以及 XML 中的和/或可能更复杂,所以我不能做一个简单的查询来找到顶部/第一个。对于这个特定的 XML,此查询有效,但不适用于其他/全部:

DECLARE @XML AS XML = '<and><and><or><leaf><comparator name="equal_uint64" package="package0"></comparator><event name="sp_statement_starting" package="sqlserver" field="object_type"></event><value>8272</value></leaf><leaf><comparator name="equal_uint64" package="package0"></comparator><event name="sp_statement_starting" package="sqlserver" field="object_type"></event><value>20038</value></leaf></or><leaf><comparator name="equal_i_sql_unicode_string" package="sqlserver"></comparator><global name="database_name" package="sqlserver"></global><value><![CDATA[SubmissionEngine]]></value></leaf></and><leaf><comparator name="equal_boolean" package="package0"></comparator><global name="is_system" package="sqlserver"></global><value>false</value></leaf></and>'
SELECT @XML
SELECT T.c.value('.', 'varchar(100)') AS result  
--,T.c.value('.') AS ObjectType
FROM   @XML.nodes('/and/and/leaf/value') T(c)  
GO  

请告知我可以查询这种类型的 XML 以从 XML 中获取 database_name 的内容/方式(如果有多个,请同时获取)

4

1 回答 1

1

再次我不确定,如果我得到这个正确,但你可以尝试更通用的搜索:

注意:我添加了另一个带有数据库名称的节点来演示,搜索既不依赖于位置也不依赖于命名。

DECLARE @xml XML=
N'<and>
  <and>
    <or>
      <leaf>
        <comparator name="equal_uint64" package="package0" />
        <event name="sp_statement_starting" package="sqlserver" field="object_type" />
        <value>8272</value>
      </leaf>
      <leaf>
        <comparator name="equal_uint64" package="package0" />
        <event name="sp_statement_starting" package="sqlserver" field="object_type" />
        <value>20038</value>
      </leaf>
    </or>
    <leaf>
      <comparator name="equal_i_sql_unicode_string" package="sqlserver" />
      <global name="database_name" package="sqlserver" />
      <value>DatabasenameHere</value>
    </leaf>
  </and>
  <leaf>
    <comparator name="equal_boolean" package="package0" />
    <global name="is_system" package="sqlserver" />
    <value>false</value>
  </leaf>
  <test>
    <anyelement name="database_name"/>
    <value>OneMoreDB</value>
  </test>
</and>';

--查询

SELECT vals.value('text()[1]','nvarchar(max)')
FROM @xml.nodes('//*[*[@name="database_name"]]/value') A(vals);

您可以将其解读为:

  • 搜索任何地方(深度搜索//
  • 找到任何元素
    • 下一级的任何元素的属性name值为“database_name”
  • 并取<value>下面的元素
于 2019-01-25T20:05:31.110 回答