Friday, 25 March 2016

Parent Package Variable in SSIS


Parent Package Variable in SSIS

There are situations wherein you need value which is assigned to variable in one package to be used in other package.

There exist a way in SSIS to access a variable defined in one(Parent) package and utilized in other(Child) package.

Just visualize a scenario where you have a Parent Package and "n" number of child packages.Through Execute Package task you are calling all child's from Parent.

All child packages should get values from Parent package.(Values can be "Server name or DB_Name")

When we want to make use of variable values which is defined and assigned in other package(let's say Parent), the place we need to target is Child Package.

Configuration Steps as follows:

1) Go to the package(child),right click anywhere in the Control Flow Designer Area and choose Package Configuration.

2) "Package Configurations Organizer" window will pop up, click on Check-box "Enable Package Configuration" which enables "ADD" button.Click Add.

3) Package Configuration Wizard(welcome page) will launch, just Click Next. (You may or may not come across this Welcome page).

4) Now when you click Next, Select Configuration Type wizard appears.

5) From the Configuration Type drop down(defaults to XML configuration file), choose Parent Package Variable.

6) Now we have reached the most important step of this article, which is nothing but defining the Parent Variable.

7) In this place, we need to give Variable Name from which we are going to pull out values. (Parent package Variable Name).
   Note: Variable Name is case sensitive and hence you need to use the same name defined in Parent Package. We all set, to assign value to the variable in the Child package.

8) Click Next, Select Properties to Export window will appear.
9) Click on Variable Name,expand Properties and click on "Value" property.
10)Click Next, Completion wizard will summarize the configuration. Click on Finish.

Now whatever value assigned to Parent Package Variable will be assigned to Child Package during run time.

Best example, i can think of is, let's say you developed package in dev environment(with OLEDB in Parent and all Child's). Time has come to move to UAT or SIT then instead of changing OLEDB connection in each and every child package if we change in Parent Package, that will be reflected in Child Package(provided your servername and dbname are configurable through expressions with variables).

Friday, 11 March 2016

How to rename files in SSIS using Script task?


Input Filenames(under my root path folder): 

DW_DATA_MAS_UNIT_03112016
DW_DATA_MAS_PARCEL_03112016
DW_DATA_TRAN_ACCOUNT_03112016
DW_DATA_TRAN_BANKDETAILS_03112016
DW_DATA_CH_ACCDETAILS_03112016

Output(in the same root path folder): I just segregated Master,Transaction and Child tables based on the keywords(MAS,TRAN,CH) present in input file.

MASTER_DW_DATA_MAS_UNIT_03112016
MASTER_DW_DATA_MAS_PARCEL_03112016
TRAN_DW_DATA_TRAN_ACCOUNT_03112016
TRAN_DW_DATA_TRAN_BANKDETAILS_03112016
CHILD_DW_DATA_CH_ACCDETAILS_03112016

Code to achive the same :

string rootfolderPath = Dts.Variables["User::SOURCE_PATH"].Value.ToString();

string[] files = Directory.GetFiles(rootfolderPath, "*.xml", SearchOption.AllDirectories);

  foreach (string s in files)
{
string trgt = "";
if(Path.GetFileName(s).contains("MAS_"))
{
targt = Path.GetDirectoryName(s) +"\\MASTER_"+ Path.GetFileName(s);
}
else if(Path.GetFileName(s).contains("TRAN_"))
{
targt = Path.GetDirectoryName(s) +"\\TRAN_"+ Path.GetFileName(s);
}
else if(Path.GetFileName(s).contains("CH_"))
{
targt = Path.GetDirectoryName(s) +"\\CHILD_"+ Path.GetFileName(s);
}

}

if (!File.Exists(targt))
{
File.Move(s, targt);
}

Explanation: 

Firstly, add a variable(to store the Root Path of the files location) and a Script Task(to rename files using C#.net).

1)
Change the variable datatype to String and assign it with a RootFolder path value.

For Ex: C:\Users\kn\Documents\NewFolder

2) 
Make the variable as ReadOnly in Script Task.

 string rootfolderPath = Dts.Variables["User::SOURCE_PATH"].Value.ToString();

Above Line copies the root path into a string variable rootfolderPath.(value is being pulled from SSIS variable)

string[] files = Directory.GetFiles(rootfolderPath, "*.xml", SearchOption.AllDirectories);

Above Line reads out all files of specified type(in root folder and sub folder directories) and store it into a array called "files".

3)
Next step is to loop through each file in an array and rename it based on the certain condition.

foreach (string s in files)
{
string trgt = "";
if(Path.GetFileName(s).contains("MAS_"))
{
targt = Path.GetDirectoryName(s) +"\\MASTER_"+ Path.GetFileName(s);
}
else if(Path.GetFileName(s).contains("TRAN_"))
{
targt = Path.GetDirectoryName(s) +"\\TRAN_"+ Path.GetFileName(s);
}
else if(Path.GetFileName(s).contains("CH_"))
{
targt = Path.GetDirectoryName(s) +"\\CHILD_"+ Path.GetFileName(s);
}
}

Example : 

Before Change : C:\Users\kn\Documents\NewFolder\DW_DATA_MAS_UNIT_03112016.txt
After  Change : C:\Users\kn\Documents\NewFolder\MASTER_DW_DATA_MAS_UNIT_03112016.txt

Note: 
Path.GetDirectoryName(C:\Users\kn\Documents\NewFolder\DW_DATA_MAS_UNIT_03112016.txt) will return the file Parent Directory i.e C:\Users\kn\Documents\NewFolder.

Path.GetFileName(C:\Users\kn\Documents\NewFolder\DW_DATA_MAS_UNIT_03112016.txt) will return file name from fully qualified path i.e DW_DATA_MAS_UNIT_03112016.txt

Variable "s" holds the existing filename and the variable "trgt" holds the new filename.

Now with the help of methods under File Class we can rename file.

if (!File.Exists(targt))
{
File.Move(s, targt);
}

Above Code will rename file by ensuring the destination location for the target filename.

Note : 
File.Exists(destination_path)
File.Move(source_path,destination_path)

Same can be done in SSIS using FOR EACH LOOP Container, File System Task and Expression Task as well.

Wednesday, 2 March 2016

Drop Constraint of a column(s) in SQL Server




How to drop particular(FK OR UQ OR DF) constraint based on given COLUMN_NAME in SQL Server?

Key Note: 
Generally you will come across this situation when you don't create CONSTRAINT NAME on your own.
When you asked to drop "only one unique constraints" on a column of a table(assume that table has 'n' unique constraints on other columns as well) for a particular column(or for a set of columns), how do you do it when all the constraint names are system generated?

--Input for a single column: TABLE_NAME & COLUMN_NAME  

DECLARE @TABLE_NAME VARCHAR(100) = 'TRANSACTION_PARCEL' 
DECLARE @COLUMN_NAME VARCHAR(100) = 'fromdate' 
DECLARE @SQL NVARCHAR(max) = '' 

SELECT @SQL += 'ALTER TABLE ' + @TABLE_NAME 
               + ' DROP CONSTRAINT ' + constraint_name + ';' 
FROM   information_schema.constraint_column_usage A 
       JOIN sys.objects B 
         ON A.constraint_name = B.NAME 
WHERE  --B.TYPE = 'UQ' AND  
  A.table_name = @TABLE_NAME 
  AND A.column_name = @COLUMN_NAME 
GROUP  BY A.constraint_name 

PRINT @SQL 

EXEC Sp_executesql 
  @SQL 


----Input for multiple columns: TABLE_NAME & COLUMN_LIST

DECLARE @TABLE_NAME VARCHAR(100) = 'TRANSACTION_PARCEL' 
DECLARE @SQL NVARCHAR(max) = '' 

SELECT @SQL += 'ALTER TABLE ' + @TABLE_NAME 
               + ' DROP CONSTRAINT ' + constraint_name + ';' 
FROM   information_schema.constraint_column_usage A 
       JOIN sys.objects B 
         ON A.constraint_name = B.NAME 
WHERE  --B.TYPE = 'UQ' AND  
  A.table_name = @TABLE_NAME 
  AND A.column_name IN ('PARCEL_BSKEY','TRAN_BSKEY','TRAN_PARCEL_BALANCE_TYPE') 
GROUP  BY A.constraint_name 

PRINT @SQL 

EXEC Sp_executesql 
  @SQL

Note: Code can be customized to pull out particular keys as well (F - foreign key, D - Default constraint, UQ - Unique constraint, PK - Primary Key constraint)

Before you drop constraint of type PK, you need to drop FK's which falls upon this PK.