2017-07-11 108 views
0

查詢XML,我有以下SQL:優化幫助從SQL Server

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 

將從數據庫返回的任何「用戶」或「UserRole的」審覈記錄指定用戶。 「用戶」的記載很容易識別,因爲這些都是關鍵的Fileds的一部分,但是「UserRole的」記錄只能由特定的屬性(其中有很多)發現:

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

所以它依賴於找到屬性名稱爲UserId,當前值爲相關用戶標識。我可以簡化這個使用存在嗎?


使用下面的回答,我能夠把我的SQL分爲:

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 = "Data.User"]') = 1 and 
    AuditXml.exist('/a:audit/a:entities/a:entity[a:keys/a:key/a:name = "UserID" and a:keys/a:key/a:value = sql:variable("@UserID")]') = 1 
) 
-- user role type 
or 
(
    AuditXml.exist('/a:audit/a:entities/a:entity[a:type = "Data.UserRole"]') = 1 and 
    AuditXml.exist('/a:audit/a:entities/a:entity/a:properties/a:property[a:name/text()="UserID" and a:current/text()=sql:variable("@UserID")]') = 1 
) 
+0

檢查。你嘗試過XML索引嗎? –

+0

@Evaldas Buinauskas我沒有。他們看起來像他們可以幫助,所以我會考慮使用它們,以及看我是否可以優化查詢。謝謝:) – bobwah

+0

是的。如果我沒有記錯,你必須首先添加一個主XML索引,然後有三種二級索引,其中之一是屬性索引。我認爲這是你要找的。 –

回答

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")]'); 
+0

偉大的,我幫助了很多我玩了一下,並更改了用戶角色sql:或 \t( \t \t AuditXml.exist('/ a:audit/a:entities/a:entity [a:type AuditXml.exist('/ a:audit/a:entities/a:entity/a:屬性/ a:屬性[a:名稱/文本] =「HOL.UserManagement.Data.UserRole」]')= 1和 \t \t ()=「UserId」和a:current/text()= sql:variable(「@ UserId」)]')\t = 1 \t) – bobwah