Вы можете попробовать это
DECLARE @xml XML=
N'<Policy>
<id>f3d25685-fb54-438d-a0e9-03e4ba5b555f</id>
<name>SG</name>
<description />
<attributes>0</attributes>
<parentPolicy>a7c603c0-8700-45ef-9165-c0134e292ee4</parentPolicy>
<sharedPasswordRev>-1</sharedPasswordRev>
<useShortChallengeResponse>false</useShortChallengeResponse>
<settings>
<privilegedUsers>
<entries>
<entry>
<name>CEO</name>
<path>CN=CEO,CN=Users,DC=sglab,DC=local</path>
<uid>27C9C6AC9311424BB332CC5AB04B047D</uid>
<serverName>192.168.7.201</serverName>
<sid>S-1-5-21-3362085216-3357124804-2073486349-1108</sid>
<type>user</type>
</entry>
<entry>
<name>Administrator</name>
<path>CN=Administrator,CN=Users,DC=sglab,DC=local</path>
<uid>EBBC4D71CD68BE4BA49BC8B6DF01F954</uid>
<serverName>192.168.7.201</serverName>
<sid>S-1-5-21-3362085216-3357124804-2073486349-500</sid>
<type>user</type>
</entry>
</entries>
</privilegedUsers>
<unknownAppsStrategy>EDITOR</unknownAppsStrategy>
</settings>
</Policy>';
- Запрос
SELECT @xml.value('(/Policy/id/text())[1]','uniqueidentifier') AS id
,@xml.value('(/Policy/name/text())[1]','nvarchar(max)') AS [name]
--Use similar lines for all the other values below `<Policy>`
,prUsrEntry.value('(name/text())[1]','nvarchar(max)') AS PrivilegedUserName
,prUsrEntry.value('(path/text())[1]','nvarchar(max)') AS PrivilegedUserpath
--Use similar lines for values within the given `<entry>`
FROM @xml.nodes('/Policy/settings/privilegedUsers/entries/entry') A(prUsrEntry);
Идея вкратце:
Мы используем прямые вызовы .value()
для получениясвойства первого уровня непосредственно из @xml
.Можно и немного легче читать, чтобы использовать nodes()
или .query()
, чтобы избежать повторного XPath, но это ухудшит производительность.
Затем мы используем FROM @xml.nodes()
, чтобы получить производную таблицуповторяющиеся элементы.Каждый <entry>
по указанному пути будет возвращен в виде строки в производной таблице со столбцом с типом XML, представляющим <entry>
по этому пути.
Теперь Wen может использовать .value()
для чтения вложенногоэлементы.Помните о относительном пути (без /
до name
).
Некоторые подсказки:
Ваш XML выглядит так, как будто он может содержать несколько различных <settings>
.Вы можете использовать запрос, подобный этому, чтобы быть более общим:
SELECT @xml.value('(/Policy/id/text())[1]','uniqueidentifier') AS id
,@xml.value('(/Policy/name/text())[1]','nvarchar(max)') AS [name]
--Use similar lines for all the other values below `<Policy>`
,prUsrEntry.value('(name/text())[1]','nvarchar(max)') AS PrivilegedUserName
,prUsrEntry.value('(path/text())[1]','nvarchar(max)') AS PrivilegedUserpath
--Use similar lines for values within the given `<entry>`
FROM @xml.nodes('/Policy/settings') A(settings)
OUTER APPLY A.settings.nodes('privilegedUsers/entries/entry') B(prUsrEntry)
--Add more APPLYs to fetch values from other `<settings>` areas
Или даже что-то подобное этому полностью универсальному подходу
SELECT @xml.value('(/Policy/id/text())[1]','uniqueidentifier') AS id
,@xml.value('(/Policy/name/text())[1]','nvarchar(max)') AS [name]
--Use similar lines for all the other values below `<Policy>`
,anySeeting.value('local-name(.)','nvarchar(max)') AS SettingName
,anyValue.value('local-name(.)','nvarchar(max)') AS ValueName
,anyValue.value('text()[1]','nvarchar(max)') AS NestedValue
FROM @xml.nodes('/Policy/settings') A(settings)
OUTER APPLY A.settings.nodes('*') B(anySeeting)
OUTER APPLY B.anySeeting.nodes('entries/entry/*') AS C(anyValue)
ОБНОВЛЕНИЕ
Это способсделать то же самое с данными таблицы:
SELECT YourXML.value('(/Policy/id/text())[1]','uniqueidentifier') AS id
,YourXML.value('(/Policy/name/text())[1]','nvarchar(max)') AS [name]
--Use similar lines for all the other values below `<Policy>`
,prUsrEntry.value('(name/text())[1]','nvarchar(max)') AS PrivilegedUserName
,prUsrEntry.value('(path/text())[1]','nvarchar(max)') AS PrivilegedUserpath
--Use similar lines for values within the given `<entry>`
FROM YourTable
OUTER APPLY YourXML.nodes('/Policy/settings/privilegedUsers/entries/entry') A(prUsrEntry);