0

I have one sql table with xml column, which holds the value like following xml format

<Security xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Dacl>
    <ACEInformation>
      <UserName>Authenticated Users</UserName>
      <Access>Allow</Access>
      <IsInherited>false</IsInherited>
      <ApplyTo>This object only</ApplyTo>
      <Permission>List Contents</Permission>
      <Permission>Read All Properties</Permission>
      <Permission>Read Permissions</Permission>
    </ACEInformation>
    <ACEInformation>
      <UserName>Local System</UserName>
      <Access>Allow</Access>
      <IsInherited>false</IsInherited>
      <ApplyTo>This object only</ApplyTo>
      <Permission>Read All Properties</Permission>
      <Permission>Read Permissions</Permission>
    </ACEInformation>
  </Dacl>
</Security>

Here, I would like get output from xml column like this

[ Allow -> Authenticated Users -> List Contents; Read All Properties; Read Permissions; -> This object only ]

To achieve this, I am using following for loop query to join values

SELECT  xmlColumn.query('for $item in/Security/Dacl/ACEInformation return("[",data($item/Access)
[1],"->",data($item/UserName)[1],"->", (for $item2 in $item/Permission return concat($item2,";")),"-
>",data($item/ApplyTo)[1],"]")').value('.','NVARCHAR(MAX)')+' ; ' From myTable

The query is working fine, but it takes too much time to give result, for 1000 rows, it is taking 2 mins...can anyone help me to improve performance of this query?.

Mikael Eriksson
  • 136,425
  • 22
  • 210
  • 281
Kevin M
  • 5,436
  • 4
  • 44
  • 46

2 Answers2

1
select (
       select '['+
                 A.X.value('(Access/text())[1]', 'nvarchar(max)')+
                 '->'+
                 A.X.value('(UserName/text())[1]', 'nvarchar(max)')+
                 '->'+
                 (
                 select P.X.value('(./text())[1]', 'nvarchar(max)')+';'
                 from A.X.nodes('Permission') as P(X)
                 for xml path(''), type
                 ).value('text()[1]', 'nvarchar(max)')+
                 '->'+
                 A.X.value('(ApplyTo/text())[1]', 'nvarchar(max)')+
               ']'
       from T.xmlColumn.nodes('/Security/Dacl/ACEInformation') as A(X)
       for xml path(''), type
       ).value('text()[1]', 'nvarchar(max)')
from myTable as T
Mikael Eriksson
  • 136,425
  • 22
  • 210
  • 281
  • Nice work... many thanks to you....it reduced my query time from 2.5 mins to 10 secs – Kevin M Nov 25 '13 at 04:16
  • @kombsh If you are on SQL Server 2012 you could probably speed this up further with [Selective XML Indexes](http://technet.microsoft.com/en-us/library/jj670108.aspx). – Mikael Eriksson Nov 25 '13 at 06:39
0

Try something like this:

DECLARE @table TABLE (ID INT, XmlCOntent XML)

INSERT INTO @Table VALUES(1, '<Security xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Dacl>
    <ACEInformation>
      <UserName>Authenticated Users</UserName>
      <Access>Allow</Access>
      <IsInherited>false</IsInherited>
      <ApplyTo>This object only</ApplyTo>
      <Permission>List Contents</Permission>
      <Permission>Read All Properties</Permission>
      <Permission>Read Permissions</Permission>
    </ACEInformation>
    <ACEInformation>
      <UserName>Local System</UserName>
      <Access>Allow</Access>
      <IsInherited>false</IsInherited>
      <ApplyTo>This object only</ApplyTo>
      <Permission>Read All Properties</Permission>
      <Permission>Read Permissions</Permission>
    </ACEInformation>
  </Dacl>
</Security>')

SELECT
    ID,
    Access = XACE.value('(Access)[1]', 'varchar(50)'),
    ApplyTo = XACE.value('(ApplyTo)[1]', 'varchar(50)'),
    AuthUser = XACE.value('(UserName)[1]', 'varchar(50)'),
    Perm1 = XACE.value('(Permission)[1]', 'varchar(50)'),
    Perm2 = XACE.value('(Permission)[2]', 'varchar(50)'),
    Perm3 = XACE.value('(Permission)[3]', 'varchar(50)')
FROM
    @table
CROSS APPLY
    XmlContent.nodes('/Security/Dacl/ACEInformation') AS XTbl(XACE)

Gives me an output of:

enter image description here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Thanks for your answer, but my need is, I have to combine all the values and get as single column – Kevin M Nov 24 '13 at 05:11