Monday, April 15, 2013

SSIS-Implement SCD type2 without using CDC transformation


1 checksum – select all of type 2 columns, and add one output column as NEW CHECKSUM

2 lookup to see whether it is new record ,

-          Lookup column : only select PK, checksum from target table

-          Mapping : only mapping PK , but should check the checksum in the lookup columns, and change the output alias to OLD_CHECKSUM

3 lookup no match output path : as the new record to add the target table

4 lookup match output path : as the existing record

5 lookup checksum

-          Lookup column : only select checksum from target table

-          Mapping : mapping checksum in the lookup columns with available columns new checksum, and change the output alias to OLD_CHECKSUM

6 Conditional Split to output the changed rows : create case 1 as NEWCHECK != OLD_CHECKSUM

7 update the targe table to change active flag to N

-          Create an External Columns as Param_0 and mapping the PK

-          UPDATE target table SET ACTIVE_FLAG='N'  WHERE TERRITORY_ID = ?

8 insert new type 2 row

 

For Loop Container


Thursday, March 28, 2013

SSRS -Create dynamic MDX dataset and tuning MDX query

How to create a dynamic MDX query
1 create a data set and select query designer
2 add all filter for the query and choose as the parameter ( after choose as the parameter , system will automatically create one parameter in you left hand of parameter folder)

3 click the design mode

4 we can start the modify the MDX query , normally we will keep the rest of after first "From" statement , coz those are the filter statement . we can deleted those highlighted part and add our own code
5 after modifying the query , we can click execute query and the system will automatically generate the columns
6 I will talk about the MDX query tuning , we may often use the crossjoin in our query , sometimes , we use function Crossjoin() , or using * to implement crossjoin ( normally when you use cube browser to drag the columns to data plant , the system will automatically use * to do crossjoin). both of crossjoin() function and * did very bad performance , coz it does not care the turple is null or not , so we should use nonemptycrossjoin() function , this function improved a lot on the performance

7 if you want to do dynamic query , there is another thing we need to pay attention , query format. normally what i did is to line up all code in the notepad, means put all code in one line , because sometimes some line termination activity ,like you click enter and start a new line,  will impact on the expression in the next step

8 click OK we will go to next step ( see the query text , it has been filled by your code )
9 click fx on right side of query and then we enter the expression window
10 next , we need to modify the commandtext , in this part , all the command text should be start with =. all the string should double quote and also we can add the parameter into the command
and then click OK . if you setup expression for query, the query design can not be used any more
you will see the query part was changed to <Exp> and gray out Query Designer

Great , we've done the setup for dynamic MDX query dataset




 

Monday, March 18, 2013

SSIS Row Level Error Tracking


Problem :
We extracted the data from Excel and load to Oracle database , sometimes the flow failed due to data issue , like length of field in Excel exceed the database length of datatype. we have to track those failed records and see what is the error message , why they are failed. this is row level error message tracking

Solution :
1 create a pl/sql procedure to extract the error message based on the error code
CREATE OR REPLACE PROCEDURE BIDW.GET_ERROR_DESCRIPTION (
   p_Error_Code   IN       NUMBER,
   x_Error_Description          OUT      VARCHAR2,
   x_return_code       OUT      NUMBER,
   x_return_msg        OUT      VARCHAR2
)
IS
BEGIN
 
   x_Error_Description := SQLERRM(p_Error_Code*-1);
   x_return_code := 0;
 
EXCEPTION
   WHEN OTHERS
   THEN
      x_return_code := -1;
      x_return_msg := SQLERRM;
      --DBMS_OUTPUT.put_line ('Others :' || SQLERRM);
END GET_ERROR_DESCRIPTION;
2 direct the destination error point to a script component and change the error option to Redirect row
 
 
3 edit the script property
A select input column, only select ErrorCode , this was automatically generated

B manually add one output

C add code
In this case , we use a parameter as connection string

Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
        '
        ' Add your code here
        '
        Dim cn As OleDbConnection = New OleDbConnection()
        Dim cmd As OleDbCommand = New OleDbCommand()
        'cn.ConnectionString = Connections.Connection.ConnectionString.ToString
        cn.ConnectionString = Variables.ConnectionStringOraOLEDBBI.ToString
        cn.Open()
        cmd.Connection = cn
        cmd.CommandText = "BIDW.GET_ERROR_DESCRIPTION"
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.AddWithValue("P_ERROR_CODE", OleDbType.VarNumeric).Value = Row.ErrorCode
        cmd.Parameters.Add("X_ERROR_DESCRIPTION", OleDbType.VarChar, 500).Direction = ParameterDirection.Output
        cmd.Parameters.Add("X_RETURN_CODE", OleDbType.VarNumeric).Direction = ParameterDirection.Output
        cmd.Parameters.Add("X_RETURN_MSG", OleDbType.VarChar, 500).Direction = ParameterDirection.Output
 
        cmd.ExecuteNonQuery()
        If (cmd.Parameters("X_RETURN_CODE").Value = 0) And (InStr(cmd.Parameters("X_ERROR_DESCRIPTION").Value.ToString, "non-ORACLE exception", CompareMethod.Text) = 0) And (InStr(cmd.Parameters("X_ERROR_DESCRIPTION").Value.ToString, "User-Defined Exception", CompareMethod.Text) = 0) Then
            Row.ErrorDescription = cmd.Parameters("X_ERROR_DESCRIPTION").Value.ToString
        Else
            Row.ErrorDescription = ComponentMetaData.GetErrorDescription(Row.ErrorCode).ToString
        End If
        cn.Close()
    End Sub
End Class
 
 
4 load the records to flat file, which caused the error
 
Three new columns added

ErrorCode and ErrorColumn are generated by red Error Output , the ErrorDescription is generated by script , which called a procedure

5 sent the error log file to someone , by using .net code
read only variable: User::varErrorFile,$Project::varMailFrom,$Project::varMailSuccSub,
$Project::varJobEnvironment,$Project::varMailTo_Success,$Project::varMailSMTPServer

    Public Sub Main(
        Dim strCommandLineArgs As String = String.Empty
        Dim strSub As String = Convert.ToString(Dts.Variables("$Project::varMailSuccSub").Value)
        Dim strEmailTo As String = Convert.ToString(Dts.Variables("$Project::varMailTo_Success").Value)
        Dim strEmailFrom As String = Convert.ToString(Dts.Variables("$Project::varMailFrom").Value)
        Dim strEnv As String = Convert.ToString(Dts.Variables("$Project::varJobEnvironment").Value)
        Dim strSMTPServer As String = Convert.ToString(Dts.Variables("$Project::varMailSMTPServer").Value)
        Dim filePath As String = Convert.ToString(Dts.Variables("varErrorFile").Value)
        Dim lineCount As Integer = 0
        Try
            If (File.Exists(filePath)) Then
                Dim the_stream As StreamReader = New StreamReader(filePath)
                While (Not the_stream.EndOfStream)
                    the_stream.ReadLine()
                    lineCount = lineCount + 1
                End While
                the_stream.Close()
            End If
        Catch ex As Exception
        End Try                                       'check the file is existing or not
 
        If (lineCount > 1) Then                        ' check whether there are data in the file
            Try
                Dim smtp As New SmtpClient(strSMTPServer)
                With smtp
                End With
                Dim message As New MailMessage
                Dim strFile As Attachment
                strFile = New Attachment(Convert.ToString(Dts.Variables("varErrorFile").Value))
                Dim strFilePath As String = Convert.ToString(Dts.Variables("varErrorFile").Value)
                strCommandLineArgs = "List of the records in error during processing of data from enrichment file –(" + strFilePath.Substring(strFilePath.LastIndexOf("\") + 1, (strFilePath.Length - 4) - strFilePath.LastIndexOf("\")) + ")" + " at " + Date.Now.ToString() + " on " + strEnv + " Environment. "
 
                With message
                    .IsBodyHtml = True
                    .Subject = "PFA " + strCommandLineArgs
                    .To.Add(strEmailTo)
                    .From = New MailAddress(strEmailFrom)
                    .Body = strCommandLineArgs
                    .Attachments.Add(strFile)
                End With
                smtp.Send(message)
            Catch ex As Exception
                ' MsgBox(ex.Message)
            End Try
        End If
        Dts.TaskResult = ScriptResults.Success
    End Sub





Friday, February 8, 2013

SSIS OLE DB Command- run a PL/SQL

PL/SQL code
DECLARE
P_BOOKINGS_SK NUMBER;
BEGIN
P_BOOKINGS_SK := ?;
DELETE FROM F_BOOKINGS WHERE BOOKINGS_SK = P_BOOKINGS_SK;
DELETE FROM B_BOOKINGS_INVOICE WHERE BOOKINGS_SK = P_BOOKINGS_SK;
DELETE FROM B_BOOKINGS_QUOTE_SN WHERE BOOKINGS_SK = P_BOOKINGS_SK;
DELETE FROM F_OIC WHERE BOOKINGS_SK = P_BOOKINGS_SK;
DELETE FROM F_OIC_BOOKINGS_BRIDGE WHERE BOOKINGS_SK = P_BOOKINGS_SK;
DELETE FROM D_BOOKINGS WHERE BOOKINGS_SK = P_BOOKINGS_SK;
END;

step 1
ole db command should have a input
 
 
step 2
under the tab of input and output properties , create external columns ( when you create multiple columns , note the parameter sequence should be same as the external columns sequence )
step 3 column mapping
step 4 type in the pl\sql code under sqlcommand

 


Thursday, January 31, 2013

SSIS pass a child package varaible value to the parent package

Introduction

my project has two package , one is child package , the other is parent package , that means in the parent package , the child package will be executed , below is data flow screen shot , in the child package , i created a variable called child_row_count , which will assign row count number

 
next is parent package , which will execute the child package , and send the child_row_count variable's value to me by email , note that there need create another variable called parent in parent package
 
next step is create script in child package , which was used to assign child package variable "child_row_count" to parent package variable "parent"
 
 
1 setup the ReadOnlyVariables and ReadWriteVariables
note that ReadWriteVariables should be parent package variable , but they are not in the list , you have to manually type in without "User:: "
 
 
2 script
 
Dts.Variables(
"parent").Value = Dts.Variables("child_row_count").Value

if you want to pass the parent package variable to child , you also can use this approach



 


SSIS: Reading and Writing to Variables in Script Task


 

SSIS: Reading and Writing to Variables in Script Task          

SSIS: Reading and Writing to Variables in Script Task

A lot of people still consistently ask me about how to read and write to variables in the SSIS script task. In this post I will demonstrate for you the two ways in which you can go about this, one from native SSIS functionality and the other from code. In SQL Server 2008 both will generally work out equally as well. In previous versions, you may want to stick with the coding piece as sometimes the a€˜automatica€™ integration with the variable dispenser was a little hooky.
So for our example, I am going to set up a simple SSIS project. First I create 2 variables: MyName & YourName. I have scoped these at the packages level as it has always been my instinct that unless there is a compelling reason to scope it otherwise.



Now that we have our variables set up, we are ready to begin making our project. Since this example is going to be pretty straightforward, we will just drop two script components onto the control flow design surface. The first will be the one using the native way of handling variables in the script component and the second will be using a little bit of custom code to do it programmatically. The setup is simply shown below.


Now opening up the script task you can click on the a€| button next to the readonlyvariables and readwritevariables areas. For this sample, I am setting up the MyName variable to be read only and the YourName variable to read-write.

 



When completed the screen will show our two variables in the boxes as shown below.



Now it is a matter of simply making a call, like below, to access your variables. For my example I am simply going to display the values in some message boxes. Reading from the MyName variable and overwriting the YourName variable. Pretty simple.
    Public Sub Main()
        Dim MyName As String = Dts.Variables("MyName").Value
        MsgBox(MyName)
        Dts.Variables("YourName").Value = "Tom"
        Dim YourName As String = Dts.Variables("YourName").Value
        MsgBox(YourName)
        Dts.TaskResult = ScriptResults.Success
    End Sub




The variables integration with the script tasks has gotten much better in SQL Server 2008 and I have yet to run into any problems like I have previously. Still, there may be some instances that you come across that you would rather programmatically access variables. For this the code below should do the trick. I have two functions: one for reading a variable and the other for writing to a variable. You will notice in both instances that you must lock the variable first before trying to access it. Think of it as SSISa€™s version of row locking. You want to make sure that you are getting the most accurate version of the variable at that point in time. What good would it do you,since things can run in parallel, if another task is updating the variable at the same time you are trying to read it?
    Public Sub Main()
        Dim MyName As String = ReadVariable("MyName")
        MsgBox(MyName)
        WriteVariable("YourName", "Tom")
        Dim YourName As String = ReadVariable("YourName")
        MsgBox(YourName)
        Dts.TaskResult = ScriptResults.Success
    End Sub
 
    Private Function ReadVariable(ByVal varName As String) As Object
        Dim rtnValue As Object
        'Create a variables collection to hold you object
        Dim var As Variables
 
        Try
            'Lock the variable first to make sure that you have exclusive access
            'Think of it like a database object lock
            Dts.VariableDispenser.LockOneForRead(varName, var)
 
            'Now populate your result
            rtnValue = var(varName).Value
        Catch ex As Exception
            Throw ex
        Finally
            'You must make sure that you unlock the variable before exiting routine
            var.Unlock()
        End Try
 
        Return rtnValue
    End Function
 
    Private Sub WriteVariable(ByVal varName As String, ByVal value As Object)
        'Create a variables collection to hold you object
        Dim var As Variables
 
        Try
            'Lock the variable first to make sure that you have exclusive access
            'Think of it like a database object lock
            Dts.VariableDispenser.LockOneForWrite(varName, var)
 
            'Now populate your result
            var(varName).Value = value
        Catch ex As Exception
            Throw ex
        Finally
            'You must make sure that you unlock the variable before exiting routine
            var.Unlock()
        End Try
 
    End Sub

Please note on the code above it is also possible to use something like the following for locking and getting the variable into your collection
  Dts.VariableDispenser.LockForRead(varName)
  Dts.VariableDispenser.GetVariables(var)

But it includes an extra step so it is not the most elegant solution. Additionally, you may notice that in the Finally block. This is not required as Microsoft a€˜promisesa€™ in their documentation that variables are automatically unlocked when the execution of the script task stops. So you can trust that will happen or call it explicitly like me just so that you will sleep better at night.
Hopefully, this helps out some of my colleagues out there that may be struggling finding a good outline of this in the documentation.


请用Ctrl+C复制后贴给好友。

由于IE浏览器升级禁用了alt+x快捷键,请用alt+q快捷键来快速进入写说说入口