问题
I am trying to query the word Simple
out the following XML Document.
The column is xml
data type, the column name is InstanceSecurity
.
<InstanceSecurity>
<Folder>
<Authorization Mode="Simple">
<Deny PrivilegeCode="Create" />
<Deny PrivilegeCode="Delete" />
<Deny PrivilegeCode="Edit" />
<Deny PrivilegeCode="Read" />
<Deny PrivilegeCode="View" />
<Deny PrivilegeCode="Print" />
<Allow PrivilegeCode="All" EntityType="Personnel" EntityVal="5bc2" />
<Allow PrivilegeCode="All" EntityType="Personnel" EntityVal="f85b" />
</Authorization>
</Folder>
</InstanceSecurity>
I've tried:
Select InstanceSecurity.query('/InstanceSecurity/Folder/Authorization[@Mode="Simple"]') AS SecuredMode
FROM Cases
AND
SELECT *
FROM Cases
WHERE InstanceSecurity.value('(/InstanceSecurity/Folder/Authorization/Mode)[1]','nvarchar(100)') like '%'
Neither one returns anything
Most examples I have looked at have a start and end tag, like
<item id="a">a is for apple</item>
not sure if that has any effect on how to query this.
Any help would be appreciated.
回答1:
It is very important to understand, what content you want to pick out of an XML. There are elements and attributes - and the floating text between element tags, the text()
node. Execute this to see the principles:
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);
Hint: Try to pick just the last one (value(N'.'),N'nvarchar(250)'
) and send the output to plain text. This includes spaces and line breaks!
The text()
(there may be more text()
nodes within one element!) is just another kind of node, coming without surrounding tags.
Your attempts (slightly changed)
Select @xml.query('/InstanceSecurity/Folder/Authorization[@Mode="Simple"]')
This returns all <Authorization>
nodes (xml typed!) where the attribute "Mode" has the content "Simple"
SELECT @xml.value('(/InstanceSecurity/Folder/Authorization/@Mode)[1]','nvarchar(100)')
(You forgot the@
before "Mode"!)
This returns the value of the attribute. In the case above this is "Simple"
About your issue
I do not really know what you want, but one of the following should point you the way
--Returns the first value of attribute @Mode
at the given path
SELECT InstanceSecurity.value(N'(/InstanceSecurity/Folder/Authorization/@Mode)[1]',N'nvarchar(250)')
FROM Cases;
--If your XML might include more than one <Authorization>
, this would return all their @Mode
attributes
SELECT auth.value(N'@Mode',N'nvarchar(250)')
FROM Cases
OUTER APPLY InstanceSecurity.nodes(N'/InstanceSecurity/Folder/Authorization') AS A(auth);
--This returns - in cases of many - all <Authorization>
elements where the @Mode
is "Simple"
SELECT auth.query(N'.')
FROM Cases
OUTER APPLY InstanceSecurity.nodes(N'/InstanceSecurity/Folder/Authorization[@Mode="Simple"]') AS A(auth);
--And this returns all table's rows where at least one @Mode
has the value "Simple"
SELECT *
FROM Cases
WHERE InstanceSecurity.exist(N'/InstanceSecurity/Folder/Authorization[@Mode="Simple"]')=1
Final hint: You can replace a literal value within XQuery
with sql:variable("@VarName")
or with sql:column("ColumnName")
.
回答2:
Try this
SELECT * FROM Cases
WHERE InstanceSecurity.value('(/InstanceSecurity/Folder/Authorization/@Mode)[1]','varchar(100)') = 'Simple'
来源:https://stackoverflow.com/questions/50167165/how-to-query-xml-column-in-tsql-for-specific-text