Вы должны попытаться вернуть как можно меньше из XML.
Лучше всего было уменьшить количество разбора двигателя до необходимого минимума.
И вам следует избегать обратной навигации, используя ../
. Это хорошо известный убийца производительности.
Попробуйте это:
DECLARE @tbl TABLE(YourXml XML);
INSERT INTO @tbl VALUES
(N'<?xml version="1.0" encoding="utf-16"?>
<ArrayOfCustomProperty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomProperty>
<DeveloperId>Test123</DeveloperId>
<Key>AgreedToTerms</Key>
<Value>True</Value>
</CustomProperty>
<CustomProperty>
<DeveloperId>Test456</DeveloperId>
<Key>ValidForLoyaltyPoints</Key>
<Value>False</Value>
</CustomProperty>
</ArrayOfCustomProperty>');
- Ваш ключ-переменная
DECLARE @key VARCHAR(100)='ValidForLoyaltyPoints' ;
- Запрос
SELECT cp.value('(DeveloperId/text())[1]','nvarchar(250)') AS DeveloperId
,cp.value('(Value/text())[1]','nvarchar(250)') AS Value
FROM @tbl t
CROSS APPLY t.YourXml.nodes('/ArrayOfCustomProperty/CustomProperty[(Key/text())[1]=sql:variable("@key")]') A(cp);
XPath/XQuery
в .nodes()
опустится до <CustomProperty>
и вернет его с <Key>
, где текст ключа подобен данному фильтру. Найденный <CustomProperty>
возвращается. Используя .value()
, мы можем прочитать элементы ниже данного свойства.
UPDATE
Выглядит так, как будто вы пытаетесь получить <Value>
как скалярное значение в зависимости от <DeveloperId>
и <Key>
. Вы можете использовать простой предикат для одновременного запроса:
DECLARE @key VARCHAR(100)='ValidForLoyaltyPoints' ;
DECLARE @devId VARCHAR(100)='Test456';
--the Query
SELECT t.YourXml.value(N'(/ArrayOfCustomProperty
/CustomProperty[(DeveloperId/text())[1]=sql:variable("@devId")
and (Key/text())[1]=sql:variable("@key")]
/Value/text())[1]',N'nvarchar(100)')
FROM @tbl t;
Вы читаете это как
- Погружение в массив
- Погрузитесь глубже в CustomProperty
- Найти элемент, где фильтр соответствует ...
- ... и вернуть его значение