SQL 2005中带有XML列的按语法排序

SQL 2005中带有XML列的按语法排序,sql,xml,xpath,Sql,Xml,Xpath,我有一个用户配置文件(基于用户类型的多个配置文件),存储在DB列(xml)中 我可以在存储过程中使用XPATH对此进行查询,但是我不确定接下来如何执行ORDER BY SELECT U.UserId, UP.Profile, UP.UserParentID FROM aspnet_Users U LEFT OUTER JOIN UserProperties UP ON U.UserId = UP.UserId WHERE UP.Profile.exist('/Properties/propert

我有一个用户配置文件(基于用户类型的多个配置文件),存储在DB列(xml)中

我可以在存储过程中使用XPATH对此进行查询,但是我不确定接下来如何执行ORDER BY

SELECT U.UserId, UP.Profile, UP.UserParentID
FROM aspnet_Users U
LEFT OUTER JOIN UserProperties UP ON U.UserId = UP.UserId
WHERE
UP.Profile.exist('/Properties/property[contains(.,sql:variable("@cLookup"))]') = 1
XML示例:

<Properties>
            <property id="BusinessName" name="Business Name"></property>
            <property id="AccountNumber" name="Account Number"></property>
            <property id="Address" name="Address"></property>
            <property id="Phone" name="Phone"></property>
            <property id="Fax" name="Fax"></property>
            <property id="Web" name="Web"></property>
            <property id="ABN" name="ABN"></property>
            <property id="Logo" name="Logo"></property>
            <property id="Photos" name="Photos"></property>
            <property id="Map" name="Location Map"></property>
        </Properties>



如果您想按BusinessName下单,请将此答案视为正在进行的工作,因为我不确定这是否是正确的查询

答案在于将.nodes()函数与.value()结合使用,这样您就可以从元素中提取“name”属性的值,并将“BusinessName”作为“id”属性的值

这里有一些使用.nodes()替换旧OPENXML语法的指南

不管怎么说,现在的问题是这样的。在您的数据上尝试一下,看看我们是否可以调整它,直到它起作用

SELECT U.UserId, UP.Profile, UP.UserParentID
FROM aspnet_Users U
    LEFT OUTER JOIN UserProperties UP ON U.UserId = UP.UserId
    OUTER APPLY UP.Profile.nodes('/Properties/property') p(prof)

WHERE UP.Profile.exist('/Properties/property[contains(.,sql:variable("@cLookup"))]') = 1
    AND p.prof.value('@id', 'nvarchar(20)') = 'BusinessName'

ORDER BY p.prof.value('@name', 'nvarchar(100)')

将此答案视为正在进行的工作,因为我不确定这是否是正确的查询

答案在于将.nodes()函数与.value()结合使用,这样您就可以从元素中提取“name”属性的值,并将“BusinessName”作为“id”属性的值

这里有一些使用.nodes()替换旧OPENXML语法的指南

不管怎么说,现在的问题是这样的。在您的数据上尝试一下,看看我们是否可以调整它,直到它起作用

SELECT U.UserId, UP.Profile, UP.UserParentID
FROM aspnet_Users U
    LEFT OUTER JOIN UserProperties UP ON U.UserId = UP.UserId
    OUTER APPLY UP.Profile.nodes('/Properties/property') p(prof)

WHERE UP.Profile.exist('/Properties/property[contains(.,sql:variable("@cLookup"))]') = 1
    AND p.prof.value('@id', 'nvarchar(20)') = 'BusinessName'

ORDER BY p.prof.value('@name', 'nvarchar(100)')

您可能希望查看的另一个选项是计算列,特别是当您有一个或几个经常需要的列时

一般来说,计算列就是这样的—一个列,它的值是从其他内容计算出来的,并且在任何时候都是最新的,而不必一直刷新它

结合XML,您可以编写一个小的存储函数,并使用它在“base”表上创建一个计算列,这样您就可以按该列进行查询和排序,而无需一直“接触”XML

在这里的例子中,您可以编写一个存储函数来检索“BusinessName”,并使其在UserProfile表中可用,如下所示:

CREATE FUNCTION dbo.GetBusinessName(@input XML)
RETURNS VARCHAR(50)
WITH SCHEMABINDING
AS BEGIN
  DECLARE @Result VARCHAR(50)

  SELECT 
    @Result = @input.value('(Properties/property[@id="BusinessName"]/@name)[1]', 'VARCHAR(50)')

  RETURN @Result
END
这定义了一个存储函数,该函数将获取您的配置文件XML并查找“id”为“Business Name”的“property”,然后返回其“Name”属性

要将其添加到UserProfile表中,请使用以下SQL代码:

ALTER TABLE UserProfile
    ADD BusinessName AS dbo.GetBusinessName(Profile) PERSISTED
这样,您就可以在表中添加一个名为“BusinessName”的新计算字段,从现在起,您可以使用这个新字段进行选择和排序,例如

SELECT ID, BusinessName FROM UserProfiles ORDER BY BusinessName
享受吧


PS:关于性能的一句话:我发现在很多情况下,这比在XML字段中不断查询XML要快得多。因此,如果您的XML中有某些元素需要经常访问,或者可能以ORDER BY语句的形式出现,那么使用计算列实际上可以大大加快速度。

您可能希望查看的另一个选项是计算列,特别是当您有一个或几个经常需要的列时

一般来说,计算列就是这样的—一个列,它的值是从其他内容计算出来的,并且在任何时候都是最新的,而不必一直刷新它

结合XML,您可以编写一个小的存储函数,并使用它在“base”表上创建一个计算列,这样您就可以按该列进行查询和排序,而无需一直“接触”XML

在这里的例子中,您可以编写一个存储函数来检索“BusinessName”,并使其在UserProfile表中可用,如下所示:

CREATE FUNCTION dbo.GetBusinessName(@input XML)
RETURNS VARCHAR(50)
WITH SCHEMABINDING
AS BEGIN
  DECLARE @Result VARCHAR(50)

  SELECT 
    @Result = @input.value('(Properties/property[@id="BusinessName"]/@name)[1]', 'VARCHAR(50)')

  RETURN @Result
END
这定义了一个存储函数,该函数将获取您的配置文件XML并查找“id”为“Business Name”的“property”,然后返回其“Name”属性

要将其添加到UserProfile表中,请使用以下SQL代码:

ALTER TABLE UserProfile
    ADD BusinessName AS dbo.GetBusinessName(Profile) PERSISTED
这样,您就可以在表中添加一个名为“BusinessName”的新计算字段,从现在起,您可以使用这个新字段进行选择和排序,例如

SELECT ID, BusinessName FROM UserProfiles ORDER BY BusinessName
享受吧

PS:关于性能的一句话:我发现在很多情况下,这比在XML字段中不断查询XML要快得多。因此,如果XML中有某些元素需要经常访问,或者可能以ORDER BY语句的形式出现,那么使用计算列实际上可以大大加快速度