Использование:IBM Cognos Analytics 11.0.7Microsoft SQL Server 2016
Начну с признания, что мои знания по синтаксическому анализу XML слабые.
Я пытаюсь использовать базу данных Cognos Audit для получения полезной информации о параметрах отчета, которые пользователи выбрали при запускеотчеты.(В частности, я подозреваю, что некоторые пользователи загружают всю витрину данных.) Я настроил ведение журнала параметров.Когда я запускаю запрос для получения информации о параметре, я вижу его в столбце с именем COGIPF_PARAMETER_VALUE_BLOB
, который представляет собой ntext, содержащий XML.У меня возникают проблемы при использовании этого XML с другими данными из базы данных аудита, поэтому я хочу составить сценарий запроса, который представит его в виде представления.
Я создал простой отчет на основе данных примера и включил несколько запросов,Когда я запускаю отчет, отвечаю на запросы и нажимаю «Готово», я вижу результирующие параметры в базе данных аудита:
<parameterValues xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:bus="http://developer.cognos.com/schemas/bibus/3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parameterValue[5]">
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Date</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 7, 2019</display>
<use xsi:type="xs:string">2019-02-07T00:00:00.000</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueSingle</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Austria</display>
<use xsi:type="xs:string">Austria</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Text</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">asdf</display>
<use xsi:type="xs:string">asdf</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">DateRange</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="boundRangeParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<end xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 14, 2019</display>
<use xsi:type="xs:string">2019-02-14T23:59:59.999</use>
</end>
<start xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 6, 2019</display>
<use xsi:type="xs:string">2019-02-06T00:00:00.000</use>
</start>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueMultiple</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[3]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Canada</display>
<use xsi:type="xs:string">Canada</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">China</display>
<use xsi:type="xs:string">China</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Denmark</display>
<use xsi:type="xs:string">Denmark</use>
</item>
</value>
</item>
</parameterValues>
Обратите внимание, что в параметре с именем ValueMultiple я выбрал три значения: Канада, Китай, Дания.
Я создал этот запрос:
select b.value('(text())[1]', 'varchar(128)') as 'ParamName'
, b.value('(../value/@arrayType)[1]', 'varchar(128)') as 'ParamType'
, b.value('(../value/item/inclusive)[1]', 'varchar(128)') as 'Inclusive'
, b.value('(../value/item/display)[1]', 'varchar(128)') as 'Display'
, b.value('(../value/item/use)[1]', 'varchar(128)') as 'Use'
--, b.value('(../value/item/start/inclusive)[1]', 'varchar(128)') as 'RangeStartInclusive'
--, b.value('(../value/item/start/display)[1]', 'varchar(128)') as 'RangeStartDisplay'
--, b.value('(../value/item/start/use)[1]', 'varchar(128)') as 'RangeStartUse'
--, b.value('(../value/item/end/inclusive)[1]', 'varchar(128)') as 'RangeEndInclusive'
--, b.value('(../value/item/end/display)[1]', 'varchar(128)') as 'RangeEndDisplay'
--, b.value('(../value/item/end/use)[1]', 'varchar(128)') as 'RangeEndUse'
from @x.nodes('/parameterValues/item/name') a(b)
order by 1
, который возвращает эту строку:
+---------------+------+---------+---------+------+
| ValueMultiple | true | Canada | Canada | NULL |
+---------------+------+---------+---------+------+
..., но не возвращает строку для Китая или Дании,Я также хочу видеть ...
+---------------+------+---------+---------+------+
| ValueMultiple | true | China | China | NULL |
+---------------+------+---------+---------+------+
| ValueMultiple | true | Denmark | Denmark | NULL |
+---------------+------+---------+---------+------+
Кроме того, вы можете видеть, что возвращаемый столбец ParamType содержит все NULL.Я попытался SOAP-ENC:arrayType
, но SQL-сервер сказал мне XQuery [value ()]: имя «SOAP-ENC» не обозначает пространство имен. Это кажется мне странным (опять же, ограниченное знание XML), потому чтоЯ вижу xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
в первой строке XML.Я могу справиться с этим, включив в свой запрос что-то вроде REPLACE(xml, 'SOAP-ENC:', '')
.
Любая помощь приветствуется, но два моих главных вопроса на данный момент:
Как сделать так, чтобы запрос выводил эти данные в пригодную для использования таблицу (включая отсутствующие строки)?Требуется ли для этого процесс ETL, который я мог бы встроить в SSIS, или есть хороший способ выполнить это в запросе SQL?
Как проверить значение атрибута SOAP-ENC:arrayType
, чтобы определить, сколько элементовв значении?Должен ли я просто использовать предложенный код REPLACE
, или есть лучший способ?