Installing SQL Server with Slipstream

Many thanks to Christian Bolton for telling me about “Slipstream” and how it can streamline your installation process.

Wikipedia defines slipstreaming as:

In computer jargon, to slipstream updates, patches or service packs means to integrate them into the installation files of their original software, so that the resulting files will allow a direct installation of the updated software.

If not directly supported by the software vendor, slipstreaming can be technically possible, depending on the updates, the structure and type of the program to be slipstreamed and of its installer, if any.

Slipstreaming is new functionality to SQL Server 2008 which allows you to install service packs and cumulative updates whilst installing the base version of SQL.

I tried it out this morning and it’s a pretty simple process to follow, the good thing about it is you can store this on the network and use it as a base installation. The guide I followed was:http://blogs.msdn.com/petersad/archive/2009/02/25/sql-server-2008-creating-a-merged-slisptream-drop.aspx which worked a treat.

The full Microsoft KB article is available here: http://support.microsoft.com/kb/955392

Unless you have the very latest installation disks this is definitely someing to squirrel away for your next installation.

New Arrival

Things have been a bit hectic recently and unfortunately have not been able to post much, there has been a good reason for the silence. In February this year my wife and I were blessed with another son “Harry”, once everything has settled down into a routine normal blogging service will resume.

Custom plural notifications in SSIS

Adding notification messages in SSIS is really quite easy once you understand how you can use expressions, one of my pet hates is receiving process notification emails that contain things like " file(s) processed" or " record(s) processed".

So, now we have a scenario with a disgruntled user how do we create a more professional looking solution? Remember that your boss and maybe even your bosses boss will probably see these emails at some point, so you should make it as perfect as possible.

Not everyone will have an SMTP server available to test the notification especially if reading from home, not to worry in this post I will use some variables to simulate the object properties instead.

Normally to write a custom mail notification one would create an expression on the "MessageSource" property of the "Send Mail Task" for this example I am simply going to create the variable @[User::MessageSource] as a String and evaluate it as an expression. If you have not done this before then click on the variable name in the variables window to select it, then in the properties window change the value of "EvaluateAsExpression" to True.

Next we are going to create an Int32 variable called "RowCount", normally I would populate this variable using a “Row count” task within a Data Transformation Task, but for simplicity we will just create the variable and set it to 2.

The third and final variable in the puzzle is the variable "Plural", again this is going to be evaluated as an expression. We can then set the value of @[User::Plural] as the following expression:

@[User::RowCount] == 1 ? "" : "s"

If you’re not familiar with SSIS expressions then in T-SQL it would look something like the following:

IF @RowCount = 1

BEGIN

SET @Plural = ""

END ELSE

BEGIN

SET @Plural = 's'

END

Now we have set our Plural variable we can now go back and create the expression for the MessageSource variable as the following:

"The successful process imported " + (DT_STR, 10, 1252) @[User::RowCount] + " record" + @[User::Plural] + ".\n\nRegards,\nYour Helpful DBA”

If you click on the "Evaluate Expression" box this will return:

The successful process imported 2 records.

Regards,

Your Helpful DBA



To test that the plural aspect works change the value of the variable RowCount to 1 and evaluate MessageSource again, this time the results will be:

The successful process imported 1 record.

Regards,

Your Helpful DBA



There we have it, if you haven’t used variables as expressions before then it’s a very useful lesson as expressions are the building blocks for practically everything in SSIS, once you’ve mastered this simple concept you will find that everything becomes much easier.

SQL Bits VI

Simon Sabin announced in his blog earlier today here details about SQLBits VI.

The event is on Friday 16th April at the Church House Conference Centre in Westminster, London and will be free!

For more information go to the SQLBits website.

New Year, New Opportunities

Like many people I have taken the steps of acquiring a new job during the New Year merry go round. After a brief search I have been offered and accepted a position as a SQL DBA at a well known UK retailer.

There have been lots of posts on forums and mailing lists asking for hints and tips on interviews and sample questions, whilst I think it is unfair to list exact questions I would expect anyone going for a SQL job to have a thorough grounding in the following areas at the very minimum:

  • The structure of a database.
  • Backing up a database, recovery models and backup types.
  • An understanding of the different indexes available.
  • Detail the steps of a maintenance plan.
  • Thorough understanding of T-SQL querying commands.

Other roles such as a BI Analyst or SQL Developer may be more specialised and so could include the following:

  • SSIS/DTS
  • SSAS
  • SSRS

If you are looking for a new job at the moment either through choice or as a victim of the recession then it would be worth having professional help with your CV. Since handing in my notice I have seen first hand at how people look at resume’s whilst managers have been looking for my replacement and from the comments I have heard basic mistakes will put potential employers off. There are a number of companies offering free advice just a click away with your favourite search engine.

Happy New Year 2010

I’d like to wish you all a happy new year in which we can all look forward to the release on SQL 2008 R2 and Powerpoint!

Merry Christmas 2009

I’d like to take this opportunity to wish you and your families a very Merry Christmas!

Installing Anti Virus on a SQL Server

It’s been quite a while since I last posted anything on this site, there’s been a lot of change behind the scenes and have a number of entries to post based on things that have happened in the last few weeks.

Earlier this week I was asked by one of our infrastructure guys when would be a good time to take down one of the servers and push out some new anti virus software using SMS (Server Management System) we arranged a suitable time where the no users would be affected but the real key issue as a DBA is to make sure that the anti virus software does not adversely affect performance.

There are differing schools of thought on whether anti virus should be applied or not because of performance reasons. If you are thinking about adding an AV solution to your SQL Servers or have already done so then please check the Microsoft KB article http://support.microsoft.com/kb/309422 to see what Microsoft recommends on this contentious issue.

Leeds SQL User Group

Join Anthony Brown and Martin Bell tomorrow for an evening on Service Broker and an introduction to SQL’s version of PowerShell. There will be a prize draw for a copy of Windows 7 Ultimate during the evening as well as other goodies.

You will need to register for this event, to do so click on the following link.

Finding Files in ActiveX

This is the second entry in the series on how you can check for the existence of files in SQL Server, in part 1 Finding files in T-SQL we covered how the undocumented sp xp_FileExists could be used.

In this entry I will be introducing an overview of the FileSystemObject which we will be using primarily to check for the existence of files.

In the first example we shall create a job called “TEST – Find Files” with 4 steps which will do the following:

  1. Create a file C:\Test.txt
    In this step we use CreateTextFile method to create our test file.
  2. Check for the existence of the file C:\ThisIsntWhatICreated.txt
    In this step we use the FileExists method to check for our test file.
  3. Delete the file C:\Test.txt
    In this step we use the DeleteFile method to delete our test file.
  4. Create a Failed step for notification purposes.
    This step is just to show that another step can be run if the file does not exist.

The code for this job can be found below:

-- Script generated by Richard Douglas 

BEGIN TRANSACTION

  DECLARE @JobID BINARY(16)

  DECLARE @ReturnCode INT

  SELECT @ReturnCode = 0

IF (SELECT COUNT(*) FROM msdb.dbo.syscategories WHERE name = N'[Test Job]') < 1

  EXECUTE msdb.dbo.sp_add_category @name = N'[Test Job]'

  -- Delete the job with the same name (if it exists)

  SELECT @JobID = job_id

  FROM   msdb.dbo.sysjobs

  WHERE (name = N'TEST - Find File')

  IF (@JobID IS NOT NULL)

  BEGIN

  -- Check if the job is a multi-server job  

  IF (EXISTS (SELECT  *

              FROM    msdb.dbo.sysjobservers

              WHERE   (job_id = @JobID) AND (server_id <> 0)))

  BEGIN

    -- There is, so abort the script 

    RAISERROR (N'Unable to import job ''TEST - Find File'' since there is already a multi-server job with this name.', 16, 1)

    GOTO QuitWithRollback

  END

  ELSE

    -- Delete the [local] job 

    EXECUTE msdb.dbo.sp_delete_job @job_name = N'TEST - Find File'

    SELECT @JobID = NULL

  END

BEGIN

  -- Add the job

  EXECUTE @ReturnCode = msdb.dbo.sp_add_job @job_id = @JobID OUTPUT , @job_name = N'TEST - Find File', @owner_login_name = suser_sname(), @description = N'No description available.', @category_name = N'[Test Job]', @enabled = 1, @notify_level_email = 0, @notify_level_page = 0, @notify_level_netsend = 0, @notify_level_eventlog = 2, @delete_level= 0

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  -- Add the job steps

  EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 1, @step_name = N'Create File', @command = N'Function Main(), @database_name = N'VBScript', @server = N'', @database_user_name = N'', @subsystem = N'ActiveScripting', @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N'', @on_success_step_id = 0, @on_success_action = 3, @on_fail_step_id = 0, @on_fail_action = 2

  FileName = "C:\Test.txt"

  Dim fso, f1

  Set fso = CreateObject("Scripting.FileSystemObject")

  Set f1 = fso.CreateTextFile(FileName, True)

  Set fso = Nothing

  Set f1 = Nothing

End Function'

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 2, @step_name = N'Find File', @command = N'' Clean Up, @database_name = N'VBScript', @server = N'', @database_user_name = N'', @subsystem = N'ActiveScripting', @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N'', @on_success_step_id = 0, @on_success_action = 3, @on_fail_step_id = 4, @on_fail_action = 4

Function Main()

      Dim FSO

      Dim File

      Dim SourceFile

      Set FSO = CreateObject("Scripting.FileSystemObject")

      FileName = "C:\ThisIsntWhatICreated.txt"

      If NOT FSO.FileExists(FileName) Then

             Call Err.Raise(60001, "File Not found")

      End If

      '

      Set File = Nothing

      Set FSO = Nothing

End Function'

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 3, @step_name = N'Delete File', @command = N'Function Main()' Check if file exists to prevent error' Clean Up, @database_name = N'VBScript', @server = N'', @database_user_name = N'', @subsystem = N'ActiveScripting', @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N'', @on_success_step_id = 0, @on_success_action = 1, @on_fail_step_id = 0, @on_fail_action = 2

      Dim oFSO

      Dim sSourceFile

      Set oFSO = CreateObject("Scripting.FileSystemObject")

      sSourceFile = "C:\Test.txt"

      '

      If oFSO.FileExists(sSourceFile) Then

            oFSO.DeleteFile sSourceFile

      End If

      '

      Set oFSO = Nothing

End Function

'

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 4, @step_name = N'Job Failed', @command = N'select 1', @database_name = N'master', @server = N'', @database_user_name = N'', @subsystem = N'TSQL', @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N'', @on_success_step_id = 0, @on_success_action = 2, @on_fail_step_id = 0, @on_fail_action = 2

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  EXECUTE @ReturnCode = msdb.dbo.sp_update_job @job_id = @JobID, @start_step_id = 1

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

  -- Add the Target Servers

  EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(local)'

  IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

COMMIT TRANSACTION

GOTO   EndSave

QuitWithRollback:

  IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION

EndSave:

 

 
The first time you run this job it should fail (unless of course you have the file C:\ThisIsntWhatICreated.txt) having run steps 1,2 and 4. If you change the second step to now look for the file C:\Test.txt for job should succeed in running the first three steps.

This has been a very simple overview of a few of the methods of the FileSystemObject, there are many more things you can do for example you may only want to proceed if the file is a certain size or of a certain date, with the FileSystemObject you can do all this and more. In fact I’ll show you how you can check the file size as well, this time we’ll use DTS (I realise it’s now two versions out of date but from the people I have spoken to lots of companies still use SQL 2000, even SQL 7 and still develop in DTS).

You can download the package here.

If you don’t want to download the package then the code below is the crux of it:

'**********************************************************************

'  Visual Basic ActiveX Script

'************************************************************************

 

Function Main()

 

    Dim FSO

    Dim File

    Dim SourceFile

 

    Set FSO = CreateObject("Scripting.FileSystemObject")

 

    FileName = DTSGlobalVariables("FileName").Value

 

    If FSO.FileExists(FileName) Then

        Set File = FSO.GetFile(FileName)

 

        If File.Size = 0 Then

            Main = DTSTaskExecResult_Success

        Else

            Main = DTSTaskExecResult_Failure

        End If

    Else

        Main = DTSTaskExecResult_Failure

    End If

 

    ' Clean Up

    Set File = Nothing

    Set FSO = Nothing

End Function

As you can see it’s pretty similar to the ActiveX we used in step two of the job with a couple of differences. The first being that we are using a global variable for the filename, this is so we could use it in a loop, read it from a table or any number of other things.

The second is that we are now also using the GetFile method that allows us to check the properties of the file itself. In this scenario we are looking at the size and saying if the file size is 0 then succeed, else fail.

To find out more about how to use the FileSystemObject you can refer to the MSDN documentation here. I hope you have found this an interesting introduction to the FileSystemObject and thank you for reading.