Очень важно понимать, какой контент вы хотите выбрать из XML. Есть элементы и атрибуты - и плавающий текст между тегами элементов, узел text()
. Выполните это, чтобы увидеть принципы:
DECLARE @xml XML=
N'<root>
<AnElement ID="1" AnAttribute="The attribute''s content">The element''s content</AnElement>
<AnElement ID="2" AnAttribute="Only the attribute" />
<AnElement ID="3">Text only</AnElement>
<AnElement ID="4" AnAttribute="nested children">
<child>This is the child''s content</child>
<child>One more child</child>
</AnElement>
<AnElement ID="5" AnAttribute="nested children">
This is text 1 within the element
<child>This is the child''s content</child>
This is text 2 within the element
<child>One more child</child>
This is text 3 within the element
</AnElement>
</root>';
SELECT elmt.value(N'@ID',N'int') ID
,elmt.value(N'@AnAttribute',N'nvarchar(250)') TheAttribute
,elmt.value(N'text()[1]',N'nvarchar(250)') TheFirstText
,elmt.value(N'text()[2]',N'nvarchar(250)') TheSecondText
,elmt.value(N'child[2]/text()[1]',N'nvarchar(250)') TheFirstTextWithinChild2
,elmt.value(N'.',N'nvarchar(250)') AS FullNodeContent
FROM @xml.nodes(N'/root/AnElement') AS A(elmt);
Подсказка: Попробуйте выбрать только последний (value(N'.'),N'nvarchar(250)'
) и отправить вывод в виде простого текста. Это включает пробелы и переносы строк!
text()
(может быть больше text()
узлов в одном элементе!) - это просто еще один вид узла , без окружающих тегов.
Ваши попытки (слегка изменены)
Выберите
@ Xml.query ( '/ InstanceSecurity / Папка / авторизации [@ Mode = "Simple"]')
Возвращает все <Authorization>
узлы (напечатаны в формате xml!), Где атрибут «Mode» имеет содержимое «Simple»
ВЫБРАТЬ
@ Xml.value ( '(/ InstanceSecurity / Папка / авторизацию / @ Mode) [1]', 'NVARCHAR (100)')
(Вы забыли @
до «Режима»!)
Возвращает значение атрибута. В приведенном выше случае это «Простой»
О вашей проблеме
Я действительно не знаю, что вы хотите, но одно из следующего должно указать вам путь
- возвращает первое значение атрибута @Mode
по заданному пути
SELECT InstanceSecurity.value(N'(/InstanceSecurity/Folder/Authorization/@Mode)[1]',N'nvarchar(250)')
FROM Cases;
- Если ваш XML может включать более одного <Authorization>
, он вернет все их @Mode
атрибуты
SELECT auth.value(N'@Mode',N'nvarchar(250)')
FROM Cases
OUTER APPLY InstanceSecurity.nodes(N'/InstanceSecurity/Folder/Authorization') AS A(auth);
- Возвращает - во многих случаях - все <Authorization>
элементов, где @Mode
- «Простой»
SELECT auth.query(N'.')
FROM Cases
OUTER APPLY InstanceSecurity.nodes(N'/InstanceSecurity/Folder/Authorization[@Mode="Simple"]') AS A(auth);
- И это возвращает все строки таблицы, где хотя бы одна @Mode
имеет значение "Простой"
SELECT *
FROM Cases
WHERE InstanceSecurity.exist(N'/InstanceSecurity/Folder/Authorization[@Mode="Simple"]')=1
Заключительный совет: Вы можете заменить буквальное значение в пределах XQuery
на sql:variable("@VarName")
или sql:column("ColumnName")
.