优化有助于从SQL服务器查询XML

时间:2017-07-11 12:06:38

标签: sql sql-server xml xpath xquery

我有以下sql:

new[]

将从指定用户的数据库返回任何“User”或“UserRole”审核记录。 “用户”记录很容易识别,因为它们是密钥文件的一部分,但“UserRole”记录只能由特定属性(其中有很多)找到:

WITH XMLNAMESPACES ('http://schemas.tempuri.org/ef/audit/2.0' as a)  
SELECT AuditLogId, AuditDate, AuditUserId, AuditEntityActions, AuditXml

FROM dbo.AuditLog
WHERE

-- user type
(
    AuditXml.exist('/a:audit/a:entities/a:entity[a:type = "HOL.UserManagement.Data.User"]') = 1 and 
    AuditXml.exist('/a:audit/a:entities/a:entity[a:keys/a:key/a:name = "UserID"]') = 1 and 
    AuditXml.exist('/a:audit/a:entities/a:entity[a:keys/a:key/a:value = sql:variable("@userId")]') = 1
)

or

-- user role type
ISNULL(DATALENGTH(AuditXml.query('
    for $prop in /a:audit/a:entities/a:entity/a:properties/a:property
    where
    /a:audit/a:entities/a:entity[a:type = "HOL.UserManagement.Data.UserRole"] and 
    $prop[a:name = "UserId"] and 
    $prop[a:current = sql:variable("@userId")]

    return $prop')),5) <> 5

所以它取决于找到属性名称为UserId,当前值是有问题的用户ID。我可以简化这个以使用存在吗?

使用下面的答案,我能够将我的sql变成:

...
<property>
  <name>UserId</name>
  <type>System.Int32</type>
  <current xsi:type="xsd:int">2571</current>
</property>
...  

1 个答案:

答案 0 :(得分:1)

您可以结合两种条件使用 XQuery谓词

DECLARE @xml XML=
N'
<root xmlns:xsi="dummy">
<property>
  <name>UserId</name>
  <type>System.Int32</type>
  <current xsi:type="xsd:int">2571</current>
</property>
<property>
  <name>SomeOther</name>
  <type>System.Int32</type>
  <current xsi:type="xsd:int">2571</current>
</property>
<property>
  <name>UserId</name>
  <type>System.Int32</type>
  <current xsi:type="xsd:int">1111</current>
</property>
<property>
  <strangeContent/>
</property>
</root>';

DECLARE @UserId INT=2571;
SELECT @xml.query(N'/root/property[name/text()="UserId" and current/text()=sql:variable("@UserId")]');