SQL-запрос XML для системной таблицы расширенных событий для объекта Session (не файла данных) в поле Предикат_XML - PullRequest
0 голосов
/ 25 января 2019

Я запрашиваю системные таблицы для расширенных событий в 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

Я могу получить строку 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>

Существует XML для database_name, и я хочу получить значение для этого.

Это очень простое расширенное событие, поэтому существует очень маленький 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 (и, если их несколько, также получить их)

1 Ответ

0 голосов
/ 25 января 2019

Опять же, я не уверен, правильно ли я понимаю, но вы можете попробовать более общий поиск:

Внимание : я добавил еще один узел с именем базы данных впродемонстрировать, что поиск не зависит ни от позиции, ни от имени.

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> ниже элемента
...