SQL Server 2005 查询XML列数据

3

我有一个名为People的表,其中包含一个数据类型为xml的列,名为properties。我使用它来存储每个人的随机信息,基本上允许人们存储未来添加的任何额外数据,而无需重新设计数据库。并非所有人的xml中都具有相同的元素。

CREATE TABLE [dbo].[Person](
 [PersonID] [bigint] IDENTITY(1,1) NOT NULL,
 [PersonType] [nvarchar](50) NULL,
 [Title] [nvarchar](5) NULL,
 [Forename] [nvarchar](60) NULL,
 [Surname] [nvarchar](60) NULL,
 [Company] [nvarchar](60) NULL,
 [Properties] [xml] NULL
)

一个 XML 的示例是:
<PropertyList xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Property Name="Class">Class A</Property>
  <Property Name="CarRegistration">123456</Property>
  <Property Name="MedicalNotes">None</Property>
</PropertyList>

首先,我找不到一条SQL查询语句,可以获取与存储在XML中的条件匹配的记录列表。

例如,如何获取所有Class="Class A"的记录。我尝试过以下查询:

SELECT 
    PersonID, 
    Properties.value('/PropertyList/Property[@Name="Class"][1]','nvarchar(50)') 
FROM Person

我知道这是错误的,但我遇到了“需要单例(或空序列)”错误,我不确定出了什么问题。
另一个问题是,我已将多个旧数据库合并成一个人员列表,但旧数据库前端仍然需要访问其数据。我的计划是为每个数据库前端创建一个视图,具有特定于其需求的布局,所有视图都链接回主要人员表。但是,其中一些字段现在存储在XML中。是否有任何方法创建视图以更新XML而不查看XML,即使它看起来和操作起来就像其他表上的视图一样。我希望我解释得正确。对于每个视图,我将有一个特定的XML属性集,我需要他们编辑,并且所有记录都将拥有它们,因此不会那么随机。
谢谢任何帮助。
1个回答

5

你的XQuery应该是:

SELECT PersonID, 
       Properties.value('(/PropertyList/Property[@Name="Class"])[1]','NVARCHAR(50)') 
FROM dbo.Person

这有帮助吗?

更新:为了让其他人更清楚 - 我在/PropertyList/Property[@Name="Class"]表达式周围添加了括号,以便这将评估可能的值列表,然后在括号后面的[1]将选择该列表中的第一个(并且通常只有一个)值(作为单例),以便将其转换为NVARCHAR(50)字符串。

value('(/PropertyList/Property[@Name="Class"])[1]','NVARCHAR(50)') 
       !                                     !

“不是”和“不同于”是不同的概念。

value('/PropertyList/Property[@Name="Class"][1]','NVARCHAR(50)') 

更新2:如果您想创建视图-当然可以,没有理由不这样做! ;-)
您肯定可以创建类似于:
CREATE VIEW dbo.YourViewName
AS
    SELECT
        PersonID, PersonType, Title, 
        ForeName, Surname, Company,
        Properties.value('(/PropertyList/Property[@Name="Class"])[1]','NVARCHAR(50)') AS 'Class',
        Properties.value('(/PropertyList/Property[@Name="CarRegistration"])[1]','NVARCHAR(50)') AS 'CarRegistration',
        Properties.value('(/PropertyList/Property[@Name="MedicalNotes"])[1]','NVARCHAR(50)') AS 'MedicalNotes'

从您的表中提取数据,并在视图中将XML“分解”为列。这是您要寻找的内容吗?

@Ash Burlaczenko:不是这样的!我在 XQuery 表达式中添加了括号(在这种情况下很重要!)没有括号(原始帖子),它会出现错误并报错-使用我的括号,它可以正常工作-仔细检查一下!! - marc_s
@marc_s:你能解释一下为什么括号会有区别吗?当然,理论上,如果属性列的值可以是具有多个/PropertyList元素的XML文档片段,则括号将意味着“命名为Class的第一个属性”和“每个PropertyList的命名为Class的第一个属性之间的区别”。但是假设每个属性列值只有一个/PropertyList元素,那就没有区别了,对吧?实际上,在他的示例中,只有一个名为“Class”的属性,因此[1]根本不应该有任何区别。 - LarsH
据我理解,括号内的 XPath 基本上返回一个 节点列表 - 通常只有一个,但它仍然是一个列表。使用 [1] 定义您对该列表中第一个元素感兴趣。在该列表上使用 /text() 只会将节点的文本表示连接在一起。但是由于XPath始终返回一个列表,而 .value() 函数仅期望单个对象,因此无论该XPath是否仅返回单个节点,都需要 [1]。 - marc_s
非常好,加上括号确实有效。谢谢。对于我关于显示XML属性表的问题有什么评论吗? - Jammy
1
@marc_s:我现在明白了。 "对于未经类型化的XML列上的以下查询,由于value()方法期望第一个参数为Singleton节点,因此需要在//author/last-name上进行序数规定。如果没有它,编译器无法确定运行时是否只会出现一个<last-name>节点。" (http://msdn.microsoft.com/en-us/library/ms345117%28SQL.90%29.aspx) 因此,上面的(b)是正确的... SQL Server XPath/XQuery编译器在某些情况下需要[1]来保证表达式始终返回仅一个节点列表。感谢您回答我的好奇心。 :-) - LarsH
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接