如何在TSQL中查询特定文本的xml列

时间:2018-05-04 04:27:18

标签: sql-server xml tsql xpath xquery

我正在尝试从以下XML文档中查询单词Simple。 该列为xml数据类型,列名为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>

我试过了:

Select InstanceSecurity.query('/InstanceSecurity/Folder/Authorization[@Mode="Simple"]') AS SecuredMode
FROM Cases

SELECT *
FROM Cases
WHERE InstanceSecurity.value('(/InstanceSecurity/Folder/Authorization/Mode)[1]','nvarchar(100)') like '%'

两者都没有返回任何内容

我看过的大多数示例都有一个开始和结束标记,比如

<item id="a">a is for apple</item>

不确定这是否会影响查询方式。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

了解您希望从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 /文件夹/授权[@模式= “简单”]')

这将返回所有<Authorization>个节点(xml类型!),其中属性“Mode”的内容为“Simple”

  

选择   @ xml.value( '(/ InstanceSecurity /文件夹/授权/ @模式)[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

最终提示:您可以使用XQuerysql:variable("@VarName")替换sql:column("ColumnName")中的文字值。

答案 1 :(得分:0)

试试这个

SELECT * FROM Cases
WHERE InstanceSecurity.value('(/InstanceSecurity/Folder/Authorization/@Mode)[1]','varchar(100)') = 'Simple'