Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nigel Wilson 939 posts 2061 karma points
    Aug 20, 2010 @ 03:26
    Nigel Wilson
    0

    Tricky MSSQL query to build XML file of members

    Hi there

    I have an existing MSSQL query that outputs Member data to an XML file that is in a similar format to Umbraco.config. I then use the saved XML for a modified XSLT search.

    Due to the number of members going forward I am looking to optimise my SQL query.

    The required output is:

    <data alias="LegalName">My Company Name</data>

    My current SQL output is:

    <data>My Company Name</data>

    The SQL query is:

    SELECT 
        -1 AS '@id', 
        (
        SELECT  
            1 AS Tag,
            NULL AS Parent, 
            cmsContentXml.nodeid AS [node!1!id],
            CAST(cmsContentXml.xml as xml).value('(node/data[@alias="coyLegalEntityName"])[1]', 'nvarchar(200)') AS [node!1!data!element]
        FROM cmsContentXml 
    where CAST(cmsContentXml.xml as xml).value('(node/@nodeType)[1]', 'varchar(max)') = '1239'  
    FOR XML EXPLICIT, TYPE) FOR XML PATH('root');

     

    Can anyone advise how to get the additional alias='LegalName' bit into the output.

    I tried the following as a hack but it didn't work but assume it is something along the lines

    [node!1!data[@alias='LegalName']!element]

    Thanks

    Nigel

     

  • Richard Soeteman 3875 posts 12037 karma points MVP
    Aug 20, 2010 @ 07:46
    Richard Soeteman
    0

    Hi Nigel,

    I've build MemberExport using a DataReader retrieving the data from the database and then build the csv file. It's fast In my testcase the export of 5000 records took 2142 milliseconds. I suggest you use a Datareader and XMLWriter for your export, then you'll have full control over the output

    Cheers,

    Richard 

  • Nigel Wilson 939 posts 2061 karma points
    Aug 23, 2010 @ 05:44
    Nigel Wilson
    0

    Hi Richard 

    Thanks for your reply.

    I currently have a script that I run to create an  XML file but for 3,000 records it is taking 30+ seconds to run and at times has even timed out during processing - ouch !

    One full node is as follows:

     

    <node id="1281" version="1386a7f6-b7ab-4f6c-98d3-05a49a3ec405" parentID="-1" level="1" 
    writerID="0" nodeType="1239" template="0" sortOrder="2" createDate="2009-12-18T10:43:31" 
    updateDate="2009-12-18T10:43:31" nodeName="Cadbury" urlName="cadbury" 
    writerName="Administrator" nodeTypeAlias="SupplierCompany" path="-1,1281" 
    loginName="cadbury" email="[email protected]">
        <data alias="coyLegalEntityName">Cadbury Limited</data>
        <data alias="lastLoginDate" />
        <data alias="foodstuffsGroup">0</data>
        <data alias="coyContactName" />
        <data alias="coyLegalTradingName">Cadbury Chocolates</data>
        <data alias="coyLogo" />
        <data alias="coyPrimaryBusinessCategory" />
        <data alias="coySecondaryBusinessCategory" />
        <data alias="coyAucklandReviewDate" />
        <data alias="coyWellingtonReviewDate" />
        <data alias="coySouthIslandReviewDate" />
        <data alias="coyAucklandVendorID" />
        <data alias="coyWellingtonVendorID" />
        <data alias="coySouthIslandVendorID" />
        <data alias="coyPhone">03 477 3400</data>
        <data alias="coyFax">03 377 3401</data>
        <data alias="coyPhysical1">Princes Street</data>
        <data alias="coyPhysical2" />
        <data alias="coyPhysicalCity">Dunedin</data>
        <data alias="coyPhysicalPostcode">9001</data>
        <data alias="coyPostal1">PO Box 123</data>
        <data alias="coyPostal2" />
        <data alias="coyCity">Dunedin North</data>
        <data alias="coyPostcode">9010</data>
        <data alias="termsOfUse" />
      </node>

     

    I therefore identified that if I could get the SQL query to the desired XML format I can then simply save the data to file.

    Doing it this way was proving much much quicker. 

    I guess my expectations were that the main umbraco.config re-creates itself very quickly and my data has a similar structure, so was hoping to be able to get similar results.

    I am beginning to think I need to reconsider how I store the data in my XMl file and start over.

    Thanks

    Nigel

  • Nigel Wilson 939 posts 2061 karma points
    Aug 24, 2010 @ 02:11
    Nigel Wilson
    0

    I have now found an old Forum post that is along the lines of what I am trying to achieve

    http://forum.umbraco.org/yaf_postst1925_Export-members-to-xml--looking-for-a-faster-way.aspx

    My query is now returning nicely structured XML data, however there is no "root" node. So far I have not been able to successfully alter the SQL query to include this, nor have I been able to get my user control to successfully write the "root" node as part of the process.

    My SQL query is:

     

    SELECT 
      1 as Tag, 
      null as Parent, 
      umbracoNode.[id] AS [node!1!id], 
      umbracoNode.[parentID] AS [node!1!parentID], 
      umbracoNode.[text] AS [node!1!nodeName], 
      '' AS [node!1!urlName], 
      cmsMember.[loginName]AS [node!1!loginName], 
      cmsMember.[email]AS [node!1!email], 
      null AS [data!2!id], 
      null AS [data!2!alias], 
      umbracoNode.[text] AS [data!2!alias],  
      null AS [data!2],  
      CAST(employerData.xml as xml).value('(node/data[@alias="coyLegalEntityName"])[1]', 'nvarchar(200)') AS [node!1!employer] 
    FROM umbracoNode 
    inner join cmsMember on umbracoNode.[id] = cmsMember.nodeId 
    inner join cmsContent on umbracoNode.[id] = cmsContent.nodeId 
    inner join cmsContentType on cmsContent.contentType = cmsContentType.nodeId 
    inner join cmsContentVersion on umbracoNode.[id] = cmsContentVersion.contentId 
    inner join umbracoUser on umbracoNode.nodeUser = umbracoUser.[id]
    inner join cmsContentXml AS employeeData ON employeeData.nodeId = umbracoNode.[id] 
    inner join cmsContentXml AS employerData ON CAST(employeeData.xml AS xml).value('(node/data[@alias="usrEmployer"])[1]', 'nvarchar(200)') = employerData.nodeId
    
    WHERE cmsContentType.[nodeId] = '1240'
    
    Union All
    
    SELECT 
      2 AS Tag, 
      1 AS Parent, 
      cmsPropertyData.contentNodeId as [node!1!id], 
      null, null, null, null, null, 
      cmsPropertyData.[id], 
      cmsPropertyType.Alias, 
      null, 
      isnull(Convert(Nvarchar(4000),dataInt), 
          isnull(Convert(Nvarchar(4000),dataDate),
              isnull(Convert(Nvarchar(4000),dataNvarchar),
                  isnull(Convert(Nvarchar(4000),dataNtext),'')))), 
      null 
    FROM 
      umbracoNode
    inner join cmsPropertyData on umbracoNode.[id] = cmsPropertyData.contentNodeId
    inner join cmsPropertyType on cmsPropertyData.propertytypeid = cmsPropertyType.[id]
    inner join cmsContentVersion on umbracoNode.[id] = cmsContentVersion.contentId
    inner join cmsContentXml AS employeeData on cmsPropertyData.contentNodeId = employeeData.nodeId
    inner join cmsContentXml AS employerData on CAST(employeeData.xml AS xml).value('(node/data[@alias="usrEmployer"])[1]', 'nvarchar(200)') = employerData.nodeId
    WHERE 
      cmsPropertyType.contentTypeId = '1240'
    ORDER BY [node!1!id], [data!2!id] 
    FOR XML Explicit

    Can anyone suggest how to add <root id="-1"> to the sql query ?

    Thanks

    Nigel

  • Lee Kelleher 3945 posts 15163 karma points MVP 10x admin c-trib
    Aug 24, 2010 @ 03:20
    Lee Kelleher
    0

    Hi Nigel,

    On that old forum post, I posted a SQL snippet for a quick way to get the XML for all the members:

    SELECT
        m.nodeId AS '@id',
        m.Email AS '@email',
        CAST(x.xml AS XML) AS '*'
    FROM
        cmsMember AS m
        INNER JOIN cmsContentXml AS x ON m.nodeId = x.nodeId
    FOR XML PATH('member'), ROOT('members'), TYPE

    The main downside of this approach is that the XML structure is like this...

    <members>
        <member id="1234" email="[email protected]">
            <node ...>
                <data alias="...">...</data>
            </node>
            ...
        </member>
    </members>

    ... with the <node> nested under the <member> element.  But I don't see that as much of a problem.

     

    From your first snippet, it looks like you need/want to filter the members before you get the XML dump? If so, I'd suggest doing that using SQL JOINs with the cmsContent table (or others) - rather than using inline XPath statements in CAST'd XML data, (that's where the timeouts WILL occur).

    A quick example:

    SELECT
        m.nodeId AS '@id',
        m.Email AS '@email',
        CAST(x.xml AS XML) AS '*'
    FROM
        cmsContent AS c
        INNER JOIN cmsMember AS m ON c.nodeId = m.nodeId
        INNER JOIN cmsContentXml AS x ON m.nodeId = x.nodeId
    WHERE
        c.contentType IN (1239, 1240)
    FOR XML PATH('member'), ROOT('members'), TYPE

    Good luck!

    Cheers, Lee.

  • Nigel Wilson 939 posts 2061 karma points
    Sep 02, 2010 @ 20:09
    Nigel Wilson
    1

    Hi Lee (and others)

    Have finally cracked the SQL - the following outputs XML in the structure I want it - all I have to do is wrap a <root> tag around it and save the file.

    Within a user control I am running the query and saving the file (approx 3000 nodes) in about 1 second.

    SELECT 
            1 as Tag,
            null as Parent,
            umbracoNode.[id] AS [node!1!id],
            umbracoNode.[text] AS [node!1!nodeName],
            cmsMember.[loginName]AS [node!1!loginName],
            null AS [data!2!id],
            null AS [data!2!alias],
            umbracoNode.[text] AS [data!2!alias], 
            null AS [data!2]
           
    FROM [Foodstuffs Suppliers].[dbo].umbracoNode
    inner join [Foodstuffs Suppliers].[dbo].cmsMember on umbracoNode.[id] = cmsMember.nodeId
    inner join [Foodstuffs Suppliers].[dbo].cmsContent on umbracoNode.[id] = cmsContent.nodeId
    inner join [Foodstuffs Suppliers].[dbo].cmsContentType on cmsContent.contentType = cmsContentType.nodeId
    inner join [Foodstuffs Suppliers].[dbo].umbracoUser on umbracoNode.nodeUser = umbracoUser.[id]

    WHERE cmsContentType.[nodeId] = '1239' AND cmsMember.[loginName] NOT LIKE 'archived%'

    Union All

    SELECT
            2 AS Tag,
            1 AS Parent,
            cmsPropertyData.contentNodeId as [node!1!id],
            null, null,
            cmsPropertyData.[id],
            cmsPropertyType.Alias,
            null,
            isnull(Convert(Nvarchar(4000),dataInt),
                    isnull(Convert(Nvarchar(4000),dataDate),
                            isnull(Convert(Nvarchar(4000),dataNvarchar),
                                    isnull(Convert(Nvarchar(4000),dataNtext),''))))

    FROM
            [Foodstuffs Suppliers].[dbo].umbracoNode
    inner join [Foodstuffs Suppliers].[dbo].cmsPropertyData on umbracoNode.[id] = cmsPropertyData.contentNodeId
    inner join [Foodstuffs Suppliers].[dbo].cmsPropertyType on cmsPropertyData.propertytypeid = cmsPropertyType.[id]
    inner join [Foodstuffs Suppliers].[dbo].cmsMember on cmsMember.nodeId = umbracoNode.id

    WHERE cmsPropertyType.contentTypeId = '1239' AND cmsMember.[loginName] NOT LIKE 'archived%' AND
            [Foodstuffs Suppliers].[dbo].cmsPropertyType.Alias IN ('coyLegalEntityName','coyLegalTradingName','coyPhysical2',
            'coyPhysicalCity','coyAucklandVendorID','coyWellingtonVendorID','coySouthIslandVendorID',
            'coyPrimaryBusinessCategory','coySecondaryBusinessCategory',
            'foodstuffsBannerGroupCompanyParent','foodstuffsBannerGroupCompany')
    ORDER BY [node!1!id], [data!2!id]
    FOR XML Explicit

    Obviously there are custom member properties within the query and the member type ID's.

    Perserverance paid off finally . . .

    Umbraco rocks!

    Nigel

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies