It’s Alive!

You may have noticed a real dearth of posts over the last couple of months. That’s been a function of two things:

  1. I’ve been very busy at work with the release of Vivid, our Excel OLAP client, and working on the upcoming releases of Mist and Hadron.
  2. My hosting company and blog software conspired to prevent me (or any of the bloggers at Agile BI) from posting or even logging into the site.

I’m still really busy at work, but I have resolved the 2nd item. New hosting company, new blog software, and everything’s up and running. Unfortunately, if you had an account on the site previously, you will need to create a new one, but hey – look at it as a chance to get that user name you always wanted :).

In any case, the posts should be back on a more regular schedule over the next few months. David Darden, Melinda Cole, and Justin James also will be posting some updates. Please let me know if you experience any problems with the new site, and I’ll try to get them addressed as soon as possible.

Posted in Uncategorized | Comments Off on It’s Alive!

SQL Server 2005 Installation Failures

Recently I was trying to install SQL Server 2005 on a workstation running Windows XP Professional SP3 and for some reason the installation kept failing. The first item in the list that failed was MSXML 6.0. After combing through the log file I found the following message: “Product: MSXML 6 Service Pack 2 (KB954459) — Configuration failed.”

According to http://support.microsoft.com/kb/968749, when SQL Server Setup tries to install MSXML 6.0 SP2, it detects that the version of MSXML 6.0 that is described in Knowledge Base article 954459 is already installed on the computer. Therefore, the validation process indicates that the current version of MSXML 6.0 should not be replaced. This stops the installation of both MSXML 6.0 and SQL Server 2005.

To work around this issue, use the Windows Installer CleanUp utility to remove references to MSXML 6.0 Service Pack 2. The Windows Installer CleanUp utility can be downloaded here: http://support.microsoft.com/kb/290301. Once installed, simply run the utility, select MSXML6 Service Pack 2 (KB954459) [6.20.1099.0] in the list and click Remove. After MSXML 6.0 has been removed then you should be able to install SQL Server 2005 without any further problems.

Posted in SQL Server | Tagged , , , | Comments Off on SQL Server 2005 Installation Failures

Moving SSIS Packages with ADO.NET Destinations Between 2008 R2 and 2008

As noted by Matt Masson from the Integration Services team, not much has changed in SSIS 2008 R2. In fact, R2 is pretty much identical, with the exception of the ADO.NET Destination. So if you are developing packages, you can build them using the 2008 or 2008 R2 version of BIDS, and they can be used in either environment successfully, as long as the package doesn’t have an ADO.NET Destination. If it does, a package developed in the 2008 R2 version of BIDS will give errors when you open on a machine with the 2008 version of SSIS installed. This is because the 2008 version of the ADO.NET Destination doesn’t know what to do with the new property added to the R2 version.

This wouldn’t be a big deal, if you could have side-by-side installs of BIDS 2008 and BIDS 2008 R2, but the install for R2 replaces the 2008 version of BIDS. So, if you need to move packages developed in 2008 R2 to 2008 (a common scenario for me), you have to do a little extra work. There are a few values that need to be removed or changed by directly editing the package XML.

As always, it’s a good idea to make a backup of your package before editing the XML directly.

Open the package in your favorite text or XML editor, and look for the section that contains <components>. Underneath that, you need to locate the <component> tag that relates to your ADO NET Destination (the sample below is easy, since the name is “ADO NET Destination”, but that’s not the typical case (you do give your components meaningful names, right?).

<component id="16" name="ADO NET Destination" componentClassID="{2E42D45B-F83C-400F-8D77-61DDE6A7DF29}" description="Writes to a database using ADO.NET provider." localeId="-1" usesDispositions="true" validateExternalMetadata="True" version="1" pipelineVersion="0" contactInfo="Writes to a database using ADO.NET provider.;Microsoft Corporation; Microsoft SqlServer v10; © 2007 Microsoft Corporation; All Rights Reserved; http://www.microsoft.com/sql/support;1">
  <properties>
    <property id="23" name="TableOrViewName" dataType="System.String" state="default" isArray="false" description="The Destination database table name." typeConverter="" UITypeEditor="Microsoft.DataTransformationServices.Controls.ModalMultilineStringEditor, Microsoft.DataTransformationServices.Controls, Version= 10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" containsID="false" expressionType="Notify">"sample"</property>
    <property id="24" name="BatchSize" dataType="System.Int32" state="default" isArray="false" description="Specify the number of rows per batch. The default is 0 which uses the same size as SSIS internal buffer. " typeConverter="" UITypeEditor="" containsID="false" expressionType="Notify">0</property>
    <property id="25" name="CommandTimeout" dataType="System.Int32" state="default" isArray="false" description="The number of seconds before a command times out. A value of 0 indicates infinite time-out. " typeConverter="" UITypeEditor="" containsID="false" expressionType="Notify">30</property>
    <property id="26" name="UseBulkInsertWhenPossible" dataType="System.Boolean" state="default" isArray="false" description="Specifies whether to use the SqlBulkCopy interface to improve the performance of bulk insert operations. Only certain providers support this interface." typeConverter="" UITypeEditor="" containsID="false" expressionType="Notify">true</property>
    <property id="27" name="UserComponentTypeName" dataType="System.String" state="default" isArray="false" description="" typeConverter="" UITypeEditor="" containsID="false" expressionType="None">Microsoft.SqlServer.Dts.Pipeline.ADONETDestination, Microsoft.SqlServer.ADONETDest, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91</property>
  </properties>

Once you’ve located the right <component> tag, you need to make two changes:

One, change the version=”1” attribute in the <component> tag to version=”0”.

<component id="16"
           name="ADO NET Destination"
           componentClassID="{2E42D45B-F83C-400F-8D77-61DDE6A7DF29}"
           description="Writes to a database using ADO.NET provider."
           localeId="-1"
           usesDispositions="true" 
           validateExternalMetadata="True" 
           version="0" 
           pipelineVersion="0" 
           contactInfo="Writes to a database using ADO.NET provider.;Microsoft Corporation; Microsoft SqlServer v10; © 2007 Microsoft Corporation; All Rights Reserved; http://www.microsoft.com/sql/support;1">

Second, remove the entire <property name=”UseBulkInsertWhenPossible> element. You can comment it out, as shown below, or just delete it.

    <property id="25" name="CommandTimeout" dataType="System.Int32" state="default" isArray="false" description="The number of seconds before a command times out. A value of 0 indicates infinite time-out. " typeConverter="" UITypeEditor="" containsID="false" expressionType="Notify">30</property>
    <!--<property id="26" name="UseBulkInsertWhenPossible" dataType="System.Boolean" state="default" isArray="false" description="Specifies whether to use the SqlBulkCopy interface to improve the performance of bulk insert operations. Only certain providers support this interface." typeConverter="" UITypeEditor="" containsID="false" expressionType="Notify">true</property>-->
    <property id="27" name="UserComponentTypeName" dataType="System.String" state="default" isArray="false" description="" typeConverter="" UITypeEditor="" containsID="false" expressionType="None">Microsoft.SqlServer.Dts.Pipeline.ADONETDestination, Microsoft.SqlServer.ADONETDest, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91</property>

If you have a lot of packages to move back and forth, you probably don’t want to hand edit this each time. I wrote a little application that will process a folder of .dtsx files, and strip the 2008 R2 information out. This is done using an XSLT transform (available in the source code). The application and source are available to download from my SkyDrive.

Posted in Uncategorized | Comments Off on Moving SSIS Packages with ADO.NET Destinations Between 2008 R2 and 2008

How to Save Yourself From Yourself

Have you ever wished there was some sort of magic “undo” button for something that you just did? Maybe you didn’t really mean to delete all 10 million records out of your table. You just forgot a little thing called a constraint. Such was the case with one of my co-workers recently. He accidentally deleted all of the tables out of the database. On the bright side though, it did give us the ability to test our disaster recovery plan!

To make sure that you don’t have to unwillingly test your disaster recovery plan, there is one easy setting to change in SSMS that will (hopefully) prevent you from making such a mistake.

A co-worker (other than the one who deleted the tables inadvertently) showed this feature of SSMS one day in a weekly code review that we have.

SSMS provides you information in the status bar regarding the server to which you are currently connected. The only bad thing about this is that no matter what server you connect to, there is no real POP of anything to differentiate between environments. You have to physically look down and see what server you are connected to. See the picture below:

Normal

In my job, I connect to Localhost, a Sandbox environment, and a QA environment. It would be nice to have the ability to, at a quick glance (ideally out of peripheral vision), be able to tell to which server I’m currently connected. To accomplish this, follow the steps below.

  • In the Object Explorer pane, click Connect —> Database Engine
  • Click Options. The Connection Properties tab is now selected.
  • Check Use custom color, then click Select to choose your custom color.
    • As a rule of thumb, I use Green for Localhost and Red for anything else (Green = Good; Red = CAREFUL!!)

Options

Now, connect to a new instance of your SQL Server, and open a new query window. Notice the status bar at the bottom of the screen:

Green

And, the nice thing is that these preferences are saved until you change them, even if SQL Management Studio is closed. So, as has been famously coined before, “Set it and forget it!!” Hopefully this little trick will save you from yourself. I know that it’s saved me a time or two!

Posted in Uncategorized | Tagged | Comments Off on How to Save Yourself From Yourself

Inconsistent Column Width in SSRS

The issue I ran into was this: I was in Design mode of a report that I was developing. No matter what I did to change the column width on my columns, in both Preview as well as when I published my report, the column widths were still off. FRUSTRATING!!

After Googling for a couple of days, and coming across some not-so-helpful answers, I finally decided to try one more thing. Being fairly new to SSRS, I decided to search to see what the difference was between a Matrix and a Table. I came across the following definition from BOL:

“Use a matrix to display grouped data and summary information. You can group data by multiple fields or expressions in row and column groups. Matrices provide functionality similar to crosstabs and pivot tables. At run time, as the report data and data regions are combined, a matrix grows horizontally and vertically on the page.”

In laymen’s terms, a Matrix is used if your report can have dynamic columns. If you don’t need that functionality, then a Table will suffice just fine.

At Last! My last-ditch attempt to circumvent this most annoying problem. I did away with my layout having a Matrix as the root, and dropped a Table into Design mode instead, and started building my report. To my delight, I could size the columns any way that I wanted to, and the formatting would stick!

Bottom Line: If you have to use a Matrix because of the reason mentioned above (dynamic columns), then formatting the layout of those columns is going to be a royal pain. If you can get away with using a Table instead, then do it. It will make your life so much easier.

Posted in Uncategorized | Comments Off on Inconsistent Column Width in SSRS

Speaking at the Carolina Code Camp

I’ll be presenting a couple of sessions at the Carolina Code Camp on Saturday, May 15th. This will be my second time presenting at the Carolina Code Camp, and I’m looking forward to it. Last time, I had great audience participation, and the event was well organized and fun.

I’ll be presenting on “Processing Flat Files with SSIS” at 8:45 AM and “Unit Testing SSIS Packages” at 12:30 PM. Looking forward to both – it should be fun.

If you are in the area, feel free to drop in – there is no charge for the Code Camp.

Posted in Uncategorized | Comments Off on Speaking at the Carolina Code Camp

T-SQL Tuesday #006 – LOBs in the SSIS Dataflow

The topic for T-SQL Tuesday #006 is LOB data, selected by this month’s host, Michael Coles. If you aren’t familiar with T-SQL Tuesdays, Michael has a nice summary in his post.

In database terms, LOBs are Large OBjects, also referred to as BLOBS (Binary Large OBjects). These are data types that can exceed the maximum row size of 8 KB in SQL Server. Most often, they are used for storing large amounts of text or binary data in the database. An example of this would be an application that stores documents in a database table. SSIS has some special features for handling LOBs in the dataflow, and this post will provide an overview of them and provide a few tips on using them wisely, as well as some approaches to keep them from killing your data flow performance.

Data Types for LOBs

LOBs are represented by three types in SSIS: DT_TEXT, DT_NTEXT, and DT_IMAGE. These map to the SQL Server types VARCHAR(MAX), NVARCHAR(MAX), and VARBINARY(MAX). Each of these types can hold 2,147,483,647 bytes, or almost 2GB of data. Columns with these data types have some special rules.

First, if you want to use them in a Derived Column expression, you’ll probably need to cast it to another type, like DT_STR or DT_WSTR, as the LOB types aren’t supported by most of the built-in functions. One thing to be careful of with this is that the entire contents of the LOB may not fit in the data type you are casting to, which will cause a truncation error. You can either set the Derived Column transformation to ignore truncation errors, or redirect error rows so you can handle the longer values differently.

If you are accessing LOBs in a Script component, you have to use the AddBlobData(), GetBlobData(), and ResetBlobData() methods on the column to get to the data.

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    System.Text.UnicodeEncoding encoding= new System.Text.UnicodeEncoding();

    Row.LOBNTEXT.AddBlobData(encoding.GetBytes("My Test String"));
    byte[] bytes = Row.LOBNTEXT.GetBlobData(0, (int)Row.LOBNTEXT.Length);
    string myString = encoding.GetString(bytes);
}

Note that you should use the System.Text.AsciiEncoding class in the above code if you are working with non-Unicode data.

Transforms for LOB Data

There are two transformations in SSIS specifically designed for working with LOB data: Import Column and Export Column. The Import Column transformation is used to import the contents of a file from disk into a column in the data flow, as a LOB. The Export Column is used to do perform the reverse operation – that is, it saves the contents of a LOB column to a file on disk. Since you can process one file per row, these transformations can be really useful for moving multiple files in and out of a database.

There’s a few good walkthroughs on using these transformations, so rather than reposting the same information, here’s a few links:

The Import Column Transformation, by James Beresford (aka BI Monkey);

The Export Column Transformation, by James Beresford (aka BI Monkey)

Importing Files Using SSIS, by me

Performance

Because these data types have the potential to hold so much data, SSIS handles them a little differently than the standard data types. They are allocated separately from regular data in the buffers. When there is memory pressure, SSIS spools buffers to disk. The potential size of LOB data makes it very likely to be spooled, which can be a pretty major performance bottleneck. To minimize it, you want to make sure that the LOB data is being spooled to a nice, fast disk that doesn’t have a lot of contention. To control what disk they are spooled to, you can set the BLOBTempStoragePath property on the Data Flow task. Note that this is a different setting than BufferTempStoragePath, which controls where regular data is spooled. Ideally, you want to make sure each of these settings points to a different physical disk.

The other item to consider is whether you actually need LOB data. In some scenarios, the LOB data types are used for convenience or because there is a possibility that a small percentage of the data would exceed the maximum length of a regular data type. If you are processing a lot of data with LOB types, and most of the LOB data is small enough to fit in an regular data type, then you may be better off using a two pass approach. In one pass, select only the data with LOB values small enough to fit in a standard data type, and cast it in the SELECT statement. SSIS will process this set of data using the normal buffer approach, which should be faster. Then, do a second pass where you select only the data that is too large for a regular data type. This will minimize the amount of data that has to be processed using LOB data types. To figure out the length of a LOB column in SQL Server, you can use the DATALENGTH function.

SELECT DATALENGTH(MyLOBColumn)
FROM MyLOBTable

As usual with performance, your mileage may vary on this one. It’s worked well for me in a few scenarios, but there’s some overhead involved in using two passes. So, as with any performance tips, test it in your environment, with a solid representative sample of your data, before implementing it in production.

There it is – a whirlwind tour of LOBs in SSIS. If you have any questions or comments, please post them.

Posted in Uncategorized | Comments Off on T-SQL Tuesday #006 – LOBs in the SSIS Dataflow

Delete Multiple Connection Managers SSIS

Have you ever wanted to save yourself some time by copying a package, renaming it, and then modifying its contents to suit your needs? What if the package that you are copying from has 60 connection managers, and your new package only needs 1? In SSIS, there is no ability to do a “select all” on the connection managers that you don’t need and delete them. So, we could go hand by hand and delete every single one by right-clicking it and clicking Delete.

But where’s the fun in that?! 🙂 I asked one of my co-workers about this scenario, and he suggested editing the XML of the package directly, which was a GREAT idea! (I wish I would have thought of that myself)

If you wish to delete these connections en masse, follow the instructions below.

1) Close your package if you currently have it open.

2) Right-click on your package and click View Code. This opens your package in XML mode.

3) Look for XML tags such as the one below (these blocks of code are the ones that you will want to delete):

<pre><DTS:ConnectionManager>

 

All you need to do now is to delete the block of code associated with the Connection Managers that you wish to delete.

That’s it! Now you don’t have to worry about wasting time trying to delete multiple Connection Managers one-by-one.

Posted in Uncategorized | Tagged , | Comments Off on Delete Multiple Connection Managers SSIS

Inconsistent Background Colors in SSRS 2008

I ran across this issue a while back and figured I’d blog about my findings. After running my issue through Google, it turns out that I wasn’t the only one with this same problem.

In SSRS, you can use the following code expression to set alternating background colors on your rows as part of the Background Color property, making the data easier to read:

=IIF(RowNumber(Nothing) MOD 2,"WhiteSmoke","White"

The only problem with this code is this: If your matrix has grouping on the dataset, then there is the possibility that your background colors can be inconsistent. Look at the image below to see an explanation of what happens when you use the above code snippet as your background color:

image

Notice on this example how the first row is White, then the next 2 are WhiteSmoke, the next White, etc. These rows should be presented as shown below (alternating White to WhiteSmoke):

image

 

To accomplish this, I derived the background in SQL Server using a case statement, and then passed that column value as the background image in SSRS.

CASE
    WHEN DENSE_RANK() OVER (ORDER BY LastName) % 2 = 1 then 'WhiteSmoke'
    ELSE 'White'
END
as BGColor

I found a great write-up relating to the different ranking functions within SQL Server here; if you’re confused about any of the ranking functions, I would suggest it as a good read. It is written to SQL Server 2005, but is also applicable to SQL Server 2008. The way that I am using the ranking function here, the case statement performs a MOD 2 (% 2) function on the LastName. If the result = 1, then we pick WhiteSmoke as the background color. Else, we choose White.

Now, all that needs to be done is to include the BGColor column as part of your dataset, and then set the Background Color property in the cells that you want to alternate (in my case, I wanted the entire row to alternate colors, so I set BGColor as the Background Color in all of my cells).

Another advantage of this approach is centralized maintenance. Say, for instance, that you have a stored procedure in which you are incorporating this code, and that stored procedure is utilized by 5 different reports. If, for some reason, your user comes back saying that they want the alternating background colors to be different, then you have to physically touch each RDL file to accommodate this change. By determining the background inside SQL Server, you only have to make the change in one place — the stored procedure.

One thing to note: Whatever you use as your order column in your case statement (in my case, I used LastName), you have to ensure that your grouping in SSRS is also set to order by that column. Else, your row colors will once again be out of order.

Hope that this write-up helps someone work around the headache that I spun my wheels working through!

NOTE: If you enable sorting on any of your columnsin SSRS, then this approach will not work. What I have found is that you can use the function that I mentioned above, and all you need to do is to ensure that your data is presented to SSRS sorted by LastName (perform the sort in your dataset query in SSRS, and the also sort your data in the Report).

=IIF(RowNumber(Nothing) MOD 2,"WhiteSmoke","White"
Posted in Uncategorized | Comments Off on Inconsistent Background Colors in SSRS 2008

Presenting at the Triad Developers Guild

I’ll be presenting at the Triad Developers Guild on Tuesday. The presentation will be on Developing Custom Components for SSIS, a topic I’ve spoken on a few times before. Here’s the abstract:

“SSIS data flows are great tools for moving data. But what if you need to go beyond the out-of-the-box components provided with SSIS? John Welch will describe how custom components are a great way to encapsulate and reuse functionality for the data flow in SSIS. He will discuss what it takes to create and deploy custom components in SSIS, review the pros and cons of using custom components instead of scripts, and discuss some of the common challenges and issues with creating them.”

I’m looking forward to the presentation – it usually generates some good discussion, and I like talking about developing for SSIS. If you are in the area, please drop by.

Posted in Uncategorized | Comments Off on Presenting at the Triad Developers Guild