November 15, 2011

Create and populate a table remotely using SMO


A love using the SQL Server Management Objects (SMO) , one of the great advantages is been able to create sql server objects and execute sql scripts remotely. One good example is when a table schema is needed from a Source to a Destination, this task can be accomplish very easy using SSIS, but, where is the challenge doing that. So I create create an SMO script that will do just that. Now that's a challenge:

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Management.Smo
Imports Microsoft.SqlServer.Management.Common
Imports System.Text


<System.AddIn.AddIn("ScriptMain", Version:="1.0", Publisher:="", Description:="")> _
<System.CLSCompliantAttribute(False)> _
Partial Public Class ScriptMain
    Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase

    Enum ScriptResults
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    End Enum

    ' The execution engine calls this method when the task executes.
    ' To access the object model, use the Dts object. Connections, variables, events,
    ' and logging features are available as static members of the Dts class.
    ' Before returning from this method, set the value of Dts.TaskResult to indicate success or failure.
    '
    ' To open Code and Text Editor Help, press F1.
    ' To open Object Browser, press Ctrl+Alt+J.
    Enum ScriptResults
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    End Enum

    Public Sub Main()


        Dim SourceServerName As String = Dts.Variables("User::str_SourceServer").Value.ToString
        Dim SourceDB As String = Dts.Variables("User::str_SourceDatabase").Value.ToString
        Dim SourceSchema As String = Dts.Variables("User::str_SourceSchema").Value.ToString
        Dim SourceTable As String = Dts.Variables("User::str_SourceTable").Value.ToString
        Dim SourceTable1 As String = SourceTable

        Dim DestServerName As String = Dts.Variables("User::str_DestinationServer").Value.ToString
        Dim DestDB As String = Dts.Variables("User::str_DestinationDatabase").Value.ToString
        Dim DestSchema As String = Dts.Variables("User::str_DestinationSchema").Value.ToString
        Dim DestTable As String = Dts.Variables("User::str_DestinationTable").Value.ToString
        Dim DestTable1 As String = DestTable
        Dim TableScript As Scripter
        Dim objectsToCopy As System.Collections.ArrayList
        Dim TableToCopy As String = SourceTable.ToLower()
        Dim DestinationTableName As String = DestTable.ToLower()


        Dim SourceServer As Server
        Dim SourceSrvConn As New ServerConnection

        Dim SourceConnStr As String = "Server=" + SourceServerName + ";Database=" + SourceDB + ";Trusted_Connection=True;"
        Dim TableScripts As System.Collections.Specialized.StringCollection
        Dim CriptingOpt As ScriptingOptions = New ScriptingOptions
        Dim DestConnStr As String = "Server=" + DestServerName + ";Database=" + DestDB + ";Trusted_Connection=True;"
        Dim col As System.Collections.Specialized.StringEnumerator




        SourceTable = SourceSchema + "." + SourceTable
        DestTable = DestSchema + "." + DestTable



        'Set Servers

        SourceSrvConn.ConnectionString = SourceConnStr
        SourceServer = New Server(SourceSrvConn)
        CriptingOpt.WithDependencies = False
        CriptingOpt.SchemaQualifyForeignKeysReferences = False
        'CriptingOpt.NoTablePartitioningSchemes = True
        CriptingOpt.NoFileGroup = True
        CriptingOpt.IncludeIfNotExists = True
        CriptingOpt.Triggers = False
        CriptingOpt.AllowSystemObjects = False
        CriptingOpt.AnsiPadding = False
        CriptingOpt.ClusteredIndexes = False
        CriptingOpt.ConvertUserDefinedDataTypesToBaseType = False
        CriptingOpt.DriAllConstraints = False
        CriptingOpt.DriAllKeys = False
        CriptingOpt.DriChecks = False
        CriptingOpt.DriForeignKeys = False
        CriptingOpt.EnforceScriptingOptions = True
        CriptingOpt.NoCollation = False
        CriptingOpt.DriPrimaryKey = True



        Dim DestinationServer As Server
        Dim DestinationConn As New ServerConnection
        DestinationConn.ConnectionString = DestConnStr
        DestinationServer = New Server(DestinationConn)
        Dim s As StringBuilder = New StringBuilder

        Try
            'Dim t As Table
            Dim t1 As Table
            Dim db As Database
            db = SourceServer.Databases(SourceDB)
            t1 = db.Tables(SourceTable1, SourceSchema)
            TableScripts = t1.Script(CriptingOpt)
            col = TableScripts.GetEnumerator
            While col.MoveNext
                s.Append(" " + col.Current.ToString)
            End While
            s.Replace(TableToCopy, DestinationTableName)
            's = Replace(s, SourceTable1, DestTable1)

            Dim Connection As New SqlClient.SqlConnection(DestConnStr)
            Dim CreateCmd As New SqlClient.SqlCommand(s.ToString, Connection)
            CreateCmd.Connection.Open()
            CreateCmd.ExecuteNonQuery()
            CreateCmd.Connection.Close()


            ' Dts.Variables("User::str_CreateTable").Value = s.ToString
            Dts.TaskResult = ScriptResults.Success
        Catch ex As Exception

            Dts.Events.FireError(0, "Create Table Failure", "Creating the table object Fail " + TableToCopy + " " + ex.Message, "", 0)
            Dts.TaskResult = ScriptResults.Failure
        Finally
            s = Nothing

        End Try

      

    End Sub

End Class

Query the status of SQL Server Agent Jobs

How many times you get something from a friend that you can't wait to shared with the SQL community.
Well no so long ago a good friend gave the below script and it has become part of my personal SQL Script arsenal, Just like my friend Bernabe told me before handing the script to me he said...Enjoy:
SELECT DISTINCT
        SUBSTRING(SYSJOBS.name, 1, 100) AS [Job Name] ,
        SYSJOBSTEPS.step_name AS JobStep ,
        SYSJOBSTEPS.command,
        SYSCATEGORIES.name AS category ,
        --SYSJOBS.description AS JobDescription ,
        SYSJOBS.date_created AS CreateDate ,
        'Enabled' = CASE WHEN SYSSCHEDULES.enabled = 0 THEN 'DISABLED'
                         WHEN SYSSCHEDULES.enabled = 1 THEN 'ENABLED'
                    END ,
-- substring(SYSSCHEDULES.name,1,30) AS [Name of the schedule],
        'Job Frequency ' = CASE WHEN SYSSCHEDULES.freq_type = 1 THEN 'ONCE'
                                WHEN SYSSCHEDULES.freq_type = 4 THEN 'DAILY'
                                WHEN SYSSCHEDULES.freq_type = 8 THEN 'WEEKLY'
                                WHEN SYSSCHEDULES.freq_type = 16
                                THEN 'Monthly'
                                WHEN SYSSCHEDULES.freq_type = 32
                                THEN 'MONTHLY RELATIVE'
                                WHEN SYSSCHEDULES.freq_type = 32
                                THEN 'START AUTOMATICALLY WHEN SQL AGENT STARTS'
                           END ,
        'Days jobs run' = CASE WHEN SYSSCHEDULES.[freq_interval] = 1
                               THEN ' SUNDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 2
                               THEN ' MONDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 3
                               THEN ' TUESDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 4
                               THEN ' WEDNESDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 5
                               THEN ' THURSDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 6
                               THEN ' FRIDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 7
                               THEN ' SATURDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 8
                               THEN ' DAILY'
                               WHEN SYSSCHEDULES.[freq_interval] = 9
                               THEN ' WEEKLY'
                               WHEN SYSSCHEDULES.[freq_interval] = 10
                               THEN 'WEEKEND'
                               WHEN SYSSCHEDULES.[freq_interval] = 62
                               THEN 'MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 64
                               THEN 'SATURDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 65
                               THEN 'SATURDAY, SUNDAY'
                               WHEN SYSSCHEDULES.[freq_interval] = 126
                               THEN 'MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY'
                          END ,
        'INTERVAL TYPE' = CASE WHEN SYSSCHEDULES.freq_subday_type = 1
                               THEN 'At the specified time'
                               WHEN SYSSCHEDULES.freq_subday_type = 2
                               THEN 'Seconds'
                               WHEN SYSSCHEDULES.freq_subday_type = 4
                               THEN 'Minutes'
                               WHEN SYSSCHEDULES.freq_subday_type = 8
                               THEN 'Hours'
                          END ,
        CAST(CAST(SYSSCHEDULES.active_start_date AS VARCHAR(15)) AS DATETIME) AS StartDate ,
        CAST(CAST(SYSSCHEDULES.active_end_date AS VARCHAR(15)) AS DATETIME) AS EndDate ,
        STUFF(STUFF(RIGHT('000000'
                          + CAST(SYSJOBSCHEDULES.next_run_time AS VARCHAR), 6),
                    3, 0, ':'), 6, 0, ':') AS Run_Time
FROM    msdb..sysjobs SYSJOBS
        INNER JOIN msdb..sysjobhistory SYSJOBHISTORY ON SYSJOBHISTORY.job_id = SYSJOBS.job_id
        INNER JOIN msdb..sysJobschedules SYSJOBSCHEDULES ON SYSJOBSCHEDULES.job_id = SYSJOBS.job_id
        INNER JOIN msdb..SysSchedules SYSSCHEDULES ON SYSSCHEDULES.Schedule_id = SYSJOBSCHEDULES.Schedule_id
        INNER JOIN msdb..sysjobsteps SYSJOBSTEPS ON SYSJOBSTEPS.job_id = SYSJOBS.job_id
        INNER JOIN msdb..syscategories SYSCATEGORIES ON SYSCATEGORIES.category_id = SYSJOBS.category_id

November 12, 2011

A deadlock was detected error

A good friend of mine call me in a desperate mode because of an particular problem they have added some changes and now the package is failing because of a deadlock against some of the variables in the package.

After some thoughts I ask how he was typically adding the variables into the ReadWriteVariables like most users,  once he said that I said "Oh Nooo" even thought that made things simple is not always the best way to ensure deadblock will happen so. I said remove the variables from the ReadWriteVariables and modify your code using the below sample code:

 Variables var = null ;
        
           Dts.VariableDispenser.LockForWrite ("User::int_Sample1");
           Dts.VariableDispenser.LockForWrite ("User::int_Sample2");
           Dts.VariableDispenser.LockForWrite ("User::dt_today");
            Dts.VariableDispenser.GetVariables (ref var );
           var["User::int_Sample1"].Value = 1;
           var["User::int_Sample2"].Value = 2;
           var["User::dt_today"].Value = DateTime.Now;

           var.Unlock();
                 Dts.TaskResult = (int)ScriptResults.Success;

He was delighted, and I explain to him developers need to act like mechanics, we love the new tools, but, once in awhile look inside the engine to get your hands dirty...

November 09, 2011

Lazy programmer

I consider myself as a lazy programmer. I believed on the motto due once, due right; during my military days there was a Sargent which we call Sargent C he always used to said "El flojo siempre trabaja doble" ( The lazy always works twice) and then he used to explain first is done quick and dirty and later has to fix what it should have done right on the first place, so as a lazy programmer I try to do things once and thing on the details of how it should be done.
Fit cum studio perfectionis, non arte

Contact Form

Name

Email *

Message *