【发布时间】:2021-05-16 16:29:57
【问题描述】:
我有一个名为“Table1”的表,表中有名为“Name”和“XMLDefinition”的列。
Name XMLDefinition
--------------------------
Name1 xmlLink1
Name2 xmlLink2
在每个 XML 中,示例如下所示:
<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<QueryView>
<QueryKey />
</QueryView>
<Description>
</Description>
<QueryFields>
<f />
<f />
</QueryFields>
<FilterFields>
<f ObjectName="TABLE5" ColumnName="ID">
<DateFilterTypes />
<FuzzyDateFilterTypes />
<MonthDayFilterTypes />
<Values>
<v>0</v>
</Values>
<TranslatedValues>
<v>No</v>
</TranslatedValues>
<DataType>Boolean</DataType>
</f>
<f ObjectName="TABLE2" ColumnName="USERID">
<DateFilterTypes />
<FuzzyDateFilterTypes />
<MonthDayFilterTypes />
<Values>
<v>B80055</v>
</Values>
<TranslatedValues>
<v>B80055</v>
</TranslatedValues>
<DataType>String</DataType>
</f>
</FilterFields>
</Query>
只要在 XML 内容中包含 ObjectName = "TABLE2" AND ColumnName = "USERID",我想从 TABLE1 返回 Name。
我已经尝试了以下,虽然它没有出错,但它返回 0 条记录:
SELECT
a.Name,
X.Y.value('(f)[1]', 'VARCHAR(MAX)') as Object
FROM TABLE1 a
OUTER APPLY a.XMLDefinition.nodes('Query/FilterFields/f') as X(Y)
WHERE X.Y.value('(ObjectName)[1]', 'VARCHAR(MAX)') = 'TABLE2'
AND X.Y.value('(ColumnName)[1]', 'VARCHAR(MAX)') = 'USERID'
我不确定我错过了什么,因为我似乎正在从 Query > FilterFields > f 向下钻取,我假设我可以根据此处的 ObjectName 和 ColumnName 进行过滤。
尝试 2 更新:
SELECT Name from TABLE1
WHERE XMLDefinition.value('(/Query/QueryView/Description/QueryFields/FilterFields/f/@ObjectName) [1] ',' varchar(max)') = 'TABLE2'
AND XMLDefinition.value('(/Query/QueryView/Description/QueryFields/FilterFields/f/@ColumnName) [1] ',' varchar(max)') = 'USERID'
通过钻取每个标签尝试此尝试后,它仍然给我 0 个结果。
尝试 3 更新:
select
a.Name,
X.Y.query(N'.') as [Object] --this returns the XML of the <f> element
from dbo.Table1 a
cross apply a.XMLDefinition.nodes('//*:f[@ObjectName="TABLE2"][@ColumnName="USERID"][1]') as X(Y);
我不知道为什么,但我尝试了这个,现在它工作并返回了我正在寻找的结果。我是 XML 新手,但我认为这行得通,因为它忽略了 f 标记之前的所有命名空间和先前的标记?
【问题讨论】:
-
是的,完全有可能。它是使用带有nodes() Method (xml Data Type) 和query() Method (xml Data Type) 方法的XPath 表达式来实现的。
-
请做一些研究,尝试一下,遇到困难再发帖。
-
您编辑到“尝试 2 更新”的 XPath 对您不起作用,因为
QueryView、Description和QueryFields不在到达 @ 所需的路径中987654331@ - 他们是FilterFields的兄弟姐妹,而不是它的父母。 -
我发布了一个尝试 3,这次成功了。使用您的原始答案,我将最后一行更改为 CROSS APPLY a.XMLDefinition.nodes('//*:f[@ObjectName="TABLE2"][@ColumnName="USERID"][1]') 为 X(是)。仍然有点困惑为什么这有效,而不是以前的方式。
-
写。尝试 3 更新...是的,命名空间很重要。如果
//f...不起作用但//*:f...起作用(使用通配符命名空间),那是因为f元素不像已发布的XML 示例那样位于匿名命名空间中。通配符命名空间可以工作,但效率不是特别高,如果在多个命名空间中声明相同的元素名称(这是允许的),有时会得到意想不到的结果。
标签: sql-server xml