Wednesday, February 21, 2007
« If your unit tests hurt you are not doin... | Main | Intent insurance? Have you got coverage... »
Rob Farley posted a very interesting codegen post on scripting objects this morning, and as a reforming codegen junky I just couldn't let it go without comment :-)

Firstly, I modified his query as so:

select quotename(si.name) as "@IndexName", quotename(ss.name) AS "@SchemaName", quotename(so.name) AS "@ObjectName",
    stuff((select ',' + quotename(sc.name)
            from sys.index_columns sic
            join sys.columns sc
                on sc.column_id = sic.column_id
            where so.object_id = sic.object_id
                and sic.index_id = si.index_id
                and sc.object_id = so.object_id
            order by sic.key_ordinal
            for xml path('')),1,1,'') as "@IndexColumns"
from sys.indexes si
join sys.objects so
    on so.object_id = si.object_id
join sys.schemas ss
    on ss.schema_id = so.schema_id
where so.type = 'U' and si.type = 1
for xml path('index'), root('indexes')


Things I'll point out:
  • Adding the extra for xml clause, this time specifying a better row element name than 'row' and also adding a document node
  • Once the outter for xml clause is in place, we can alias the columns using @ to have them come out as elements in the results
We can feed the results of that query straight into the following XSLT:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"
/>
   
    <xsl:template match='/'>
    <xsl:apply-templates select ='indexes/index'
/>
    </xsl:template>

  <xsl:template match='index' >
create index <xsl:value-of select='@IndexName'
/>
  on <xsl:value-of select='@SchemaName'
/>.<xsl:value-of select='@ObjectName'/> (<xsl:value-of select='@IndexColumns'/>)
  </xsl:template>
 
</xsl:stylesheet>

I'm not claiming this method is superior, just different, which I think is in keeping with the spirit of Rob's post :-)  and I have learned more about the improvements of the for xml clause in SQL Server 2005 in the process.

I'll leave final judgment on the utility of this approach as an exercise to the reader; my instinctive reaction is to include it as a build step to help you snapshot schema changes between check-ins, or as Rob suggests to take objects from one database and create slightly different objects in another database – there are no wrong answers and if you think of something interesting please leave a comment :-)

Grab the source files here: ScriptObjects.zip (.78 KB)
Thursday, February 22, 2007 8:07:29 AM (AUS Eastern Standard Time, UTC+10:00)
Well, it depends on what you're after. My script creates a column which you can copy and paste straight into a Query Window. But your one might be more suitable for ripping apart in managed code.

Nice though... good to see people thinking about it some more.

Rob
Friday, February 23, 2007 11:33:08 AM (AUS Eastern Standard Time, UTC+10:00)
Thanks for taking the time to comment Rob

You and I hvae been here before mate :-)
http://msmvps.com/blogs/robfarley/archive/2007/01/03/removing-all-the-rows-bar-one-per-customer-from-a-table.aspx

...and thanks for teaching me something new again!
Comments are closed.