Tuesday, June 10, 2014

sp_MSforeachdb procedure to iterate through each database

Handy SQL Server system stored procedure to iterate through each databse on a server. I used to get a list of all databases that have sysssislog table present

DECLARE @DB TABLE (DBName sysname);
INSERT INTO @DB
EXEC sp_msforeachdb 'select ''?'' from [?].sys.tables t WHERE t.name = ''sysssislog'''
SELECT * FROM @DB
WHERE DBName NOT IN ('master','tempdb','model','msdb')


The undocumented sp_MSforeachdb procedure

Thursday, June 5, 2014

PowerShell: Importing CSV into SQL Server

http://www.sqlteam.com/article/fast-csv-import-in-powershell-to-sql-server

I was working on the CSV import script in PowerShell, following the first example in the article above: Simple CSV Import using PowerShell.

I had to use Out-DataTable function  from here:
http://gallery.technet.microsoft.com/scriptcenter/4208a159-a52e-4b99-83d4-8048468d29dd#content
Simple CSV Import using PowerShell
Simple CSV Import using PowerShell
Simple CSV Import using PowerShell

to get DataTable from CSV file. This part worked very well.

But then I started getting an issue at the bulk insert - "The given value of type String from the data source cannot be converted to type int of the specified target column."

After some time of looking for the culprit data row, I realized that this error happens when we try to insert an empty value in the int column.

Thus, I had to change the Out-DataTable function in the following way:

 replace

     $DR.Item($property.Name) = $property.value

by

if($property.value -eq "")
{
        $DR.Item($property.Name) = $null
}
else
{
         $DR.Item($property.Name) = $property.value
}

now, Bulk Insert is satisfied and inserts NULLs when the data is not available in the CSV





Simple CSV Import using PowerShell

Wednesday, June 4, 2014

PowerShell: searching in the first 2 levels of the directory

Let's say you need to find a certain folder in the Directory, but you don't want to go deeper than 2 or 3 levels in your search?

Obviously, we will have to use get-childitem

However, -recurse option cannot help, since it has no stopping limit - it will recurse to the bottom of the directory

Here is a solution that I found that's short and simple, just the way I like it:



$search1 = "C:\temp\*"
$search2 = "C:\temp\*\*"
$search3 = "C:\temp\*\*\*"

$folders =  Get-ChildItem  -path $search1, $search2, $search3 | where-object {$_.PSIscontainer -and $_.name.StartsWith("Blue")}

...

Monday, June 2, 2014

Continue SSIS Package execution after failure and ignoring the error

Finally found what I needed to avoid SSIS from failing the package and ignoring the error in the Task:

http://www.timmitchell.net/post/2013/08/05/continue-package-execution-after-error-in-ssis/

Just one tiny hidden System variable "Propagate" was able to resolve my issue on custom error handling in the SSIS Package.

Monday, May 26, 2014

Indexed Views | Creating and Optimizing Views in SQL Server | InformIT

Indexed Views | Creating and Optimizing Views in SQL Server | InformIT

Looks like not is all that simple with indexed views.
If we are using Standard Edition, then indexed views will be used only when we specifically use SELECT with NOEXPAND hint

Enterprise edition's query optimizer decides himself whether to use data in the indexed view, or in its underlying tables, depending on what is faster for him.

In the Standard edition, however, it doesn't bother and goes to underlying tables right away, unless you add this NOEXPAND hint.

At least this is my understanding of the articles below.

http://technet.microsoft.com/en-us/library/ms181151%28v=sql.105%29.aspx

Improving Performance with SQL Server 2005 Indexed Views

Wednesday, May 21, 2014

Converting CSV files into XML files using PowerShell

At work I have to  resort sometimes to PowerShell to provide a quick solution to a problem.

For example, I had to do some CSV conversions and manipulations, which seemed to be easier done in PowerShell rather than in SQL Server.

1. I will document here a CSV to XML file conversion, which looked to me short and sweet:

Idea inspired from http://blogs.msdn.com/b/powershell/archive/2007/05/29/using-powershell-to-generate-xml-documents.aspx

#create xml file - export_xml 
$file = "C:\tmp\file.csv"
$fileoutxml = "C:\tmp\file.xml"
$xml=Import-Csv $file -Delimiter ";" -Header "c1","c2","c3" |
 foreach { " <row c1=
`"{0}`" c2=`"{1}`" c3=`"{2}`"/>`n" -f
 $_.c1,$_.c2,$_.c3 } 

$xml="<export key_field=`"c1`">`n " + $xml + "</export>" | Out-File $fileoutxml -Encoding UTF8 

2. and a replace with Regular Expressions:
here, I am first replacing ; by | and trimming up the data at the same time
and then changing the swapping the order of the two last columns. it is important that $2$1 is surrounded by single quotes - script stops working if we use double quotes for some reason.

(Get-Content $file ) |
Foreach-Object {$_ -replace "(\s*;\s*)", -replace "(?<=^[^|]*\|[^|]*)(\|[^|]*)(\|[^|]*$)", '$2$1'; } |
Set-Content $
fileout -Encoding Unicode

Wednesday, May 7, 2014

C# supporting different versions of SQL Server with same application

I had to write a piece of code that would work for both SQL Server 2008 R2 and SQL Server 2014

There were several issues - first of them is how to include two versions of the same assembly (Microsoft.SQLServer.ManagedDTS v.10 and v.12) in the same project.

This was solved with extern alias after following instructions in this article: http://kentb.blogspot.ca/2008/11/visual-studio-referencing-same-assembly.html

Then there was a problem of ILMerge.exe which stopped working with extern alias complaining that "Unresolved assembly reference not allowed". I had to ditch ILMerge and use an alternative method described here - http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

Then I had to use reflection to maintain same code for both versions. All compiled and worked well until I tried the application on a server which really had a single version of SQL Server - 2008 R2.

I started getting the very obscure "Object reference not set to instance of an object" exception just before entering the function that used reflection.

 As it turns out you have to separate the code that uses a possibly missing library in a separate function and then all will work as it is supposed to.

Here is the code:


using dtr120 = DTS120::Microsoft.SqlServer.Dts.Runtime; 
using dtr100 = DTS100::Microsoft.SqlServer.Dts.Runtime; 

//DTS120 and DTS100 are extern aliases of two different versions of the library 

//generic method
LoadPackage<T>(string sDTSPatch)
{....} 

this doesn't work:

if (is120) //if 2014
   bFlag = LoadPackage<dtr120.Application>(sDTSPatch);
else if (is100)  //if 2008 R2
   bFlag = LoadPackage<dtr100.Application>(sDTSPatch);

but this works:

protected bool Load120(string sDTSPatch)
{
  return LoadPackage
<dtr120.Application>(sDTSPatch);
}

protected bool Load100(string sDTSPatch)
{
  return LoadPackage
<dtr100.Application>(sDTSPatch);
}

....

if (is120) //if 2014  
    bFlag = Load120(sDTSPatch);
else if (is100) //if 2008 R2
    bFlag = Load100(sDTSPatch);



Update:

I forgot to mention that you would have to automate refreshing of .dll files into the root project directory. EmbeddedResourse dll files work only if they are in the root of the project directory

I did it by writing a Pre-build event

if $(ConfigurationName) == Release (
echo f | xcopy /F /Q /Y $(ProjectDir)ProjectX\bin\Release\ProjectX.dll $(ProjectDir)ProjectX.dll
echo f | xcopy /F /Q /Y $(ProjectDir)ProjectY\bin\Release\ProjectY.dll $(ProjectDir)ProjectY.dll)

if $(ConfigurationName) == Debug (
echo f | xcopy /F /Q /Y $(ProjectDir)ProjectX\bin\Debug\ProjectX.dll $(ProjectDir)ProjectX.dll
echo f | xcopy /F /Q /Y $(ProjectDir)ProjectY\bin\Debug\ProjectY.dll $(ProjectDir)ProjectY.dll)