{"id":529,"date":"2012-02-09T04:22:26","date_gmt":"2012-02-09T04:22:26","guid":{"rendered":"http:\/\/bicortex.com\/?p=529"},"modified":"2012-02-09T21:36:46","modified_gmt":"2012-02-09T21:36:46","slug":"incremental-table-update-using-ssis","status":"publish","type":"post","link":"https:\/\/bicortex.com\/bicortex\/incremental-table-update-using-ssis\/","title":{"rendered":"Incremental Table Update Using SSIS"},"content":{"rendered":"<p style=\"text-align: justify;\">In this post I will demonstrate how to update a table (let\u2019s call it a destination table) with data from another table (let\u2019s call this one source table) based on the differences between the two via a SQL Server Integration Services package. This exercise can achieve the same result through a number of different implementation methods but since SSIS is a godsend for any kind of data transfer\/manipulation automation, this process can be scheduled and left to its own devises. Also, as SSIS is very transparent about its processing (we can readily see what is happening and troubleshoot accordingly) and to build (who would want to write code when you can drop a few containers, stitch them together and consider it done!), this method is brain-dead and quick to develop\/deploy. Doing it via SSIS also provides an option to handle errors in a more elegant way and in a single pass-through.<\/p>\n<p style=\"text-align: justify;\">So let\u2019s start with creating two new tables which will become our data source and destination as well as populating them with some dummy data via the following queries. This will form our core data source which we will use to execute incremental update against based on the difference between them.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n--CREATE SOURCE TABLE\r\nIF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'&#x5B;dbo].&#x5B;tbl_Source]') AND type in (N'U'))\r\nDROP TABLE &#x5B;dbo].&#x5B;tbl_Source]\r\n\r\nCREATE TABLE &#x5B;dbo].&#x5B;tbl_Source](\r\n\t&#x5B;Item_SKU] &#x5B;int] NULL,\r\n\t&#x5B;Item_Name] &#x5B;varchar](100) NULL,\r\n\t&#x5B;Item_Category] &#x5B;varchar](50) NULL,\r\n\t&#x5B;Item_Price] &#x5B;money] NULL,\r\n\t&#x5B;Item_Availability_Flag] &#x5B;char](1) NULL,\r\n\t&#x5B;Item_Discount_Flag] &#x5B;char](1) NULL\r\n) ON &#x5B;PRIMARY]\r\n\r\n--POPULATE SOURCE TABLE WITH DUMMY DATA\r\nINSERT INTO tbl_Source\r\nVALUES (2299, 'Pen', 'Stationary', 2.50, 'Y', 'Y');\r\nINSERT INTO tbl_Source\r\nVALUES (2212, 'Binder' , 'Stationary' , 2.10, 'Y', 'Y');\r\nINSERT INTO tbl_Source\r\nVALUES (1217, 'Scissors' , 'Stationary' , 3.20, 'N', 'N');\r\n\r\n--CREATE DESTINATION TABLE\r\nIF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'&#x5B;dbo].&#x5B;tbl_Destination]') AND type in (N'U'))\r\nDROP TABLE &#x5B;dbo].&#x5B;tbl_Destination]\r\n\r\nCREATE TABLE &#x5B;dbo].&#x5B;tbl_Destination](\r\n\t&#x5B;Item_SKU] &#x5B;int] NULL,\r\n\t&#x5B;Item_Name] &#x5B;varchar](100) NULL,\r\n\t&#x5B;Item_Category] &#x5B;varchar](50) NULL,\r\n\t&#x5B;Item_Price] &#x5B;money] NULL,\r\n\t&#x5B;Item_Availability_Flag] &#x5B;char] (1) NULL,\r\n\t&#x5B;Item_Discount_Flag] &#x5B;char](1) NULL\r\n) ON &#x5B;PRIMARY]\r\n\r\n--POPULATE DESTINATION TABLE WITH DUMMY DATA\r\nINSERT INTO tbl_Destination\r\nVALUES (2299, 'Pen', 'Stationary', 2.50,'Y', 'Y');\r\n\r\n--SELECT DATA OUT OF BOTH TABLES\r\nSELECT * FROM tbl_Source;\r\nSELECT * FROM tbl_Destination;\r\n<\/pre>\n<p style=\"text-align: justify;\">The output from the above constitutes of two tables, source table has three items with their corresponding categories, price, SKU number etc., whereas, destination table has only one item. Based on this premise we need to update destination table with the missing two items from source table via SSIS package.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_base_data\/\" rel=\"attachment wp-att-535\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-535\" title=\"SSIS_Incremental_Tbl_Update_Base_Data\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_Base_Data.png\" alt=\"\" width=\"580\" height=\"152\" srcset=\"https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Base_Data.png 580w, https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Base_Data-300x78.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The package will only require one Data Flow Task on the Control Flow pane and most of the work will involve Data Flow components adjustments.<\/p>\n<p style=\"text-align: justify;\">Let\u2019s start by placing a Data Flow component from Toolbox onto the project surface area. Next, in the Data Flow Area we place two OLE DB Source components representing the two tables we previously created i.e. tbl_Source and tbl_Destination.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_control_flow\/\" rel=\"attachment wp-att-548\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-548\" title=\"SSIS_Incremental_Tbl_Update_Control_Flow\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_Control_Flow.png\" alt=\"\" width=\"580\" height=\"101\" srcset=\"https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Control_Flow.png 580w, https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Control_Flow-300x52.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">After configuring connections and selecting all columns from both sources we can place two Sort Data Flow components which should link to the OLE DB Source containers. Also, to configure Sort containers, we only specify Item_SKU column, while all remaining attributes are set as \u2018Pass Through\u2019 as per below. This is because we will compare tables by looking only at their Item_SKU fields, which should be distinct (can act as primary keys). This is an important feature of this process.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_sort_component\/\" rel=\"attachment wp-att-555\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-555\" title=\"SSIS_Incremental_Tbl_Update_Sort_Component\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_Sort_Component.png\" alt=\"\" width=\"580\" height=\"400\" srcset=\"https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Sort_Component.png 599w, https:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/2012\/02\/SSIS_Incremental_Tbl_Update_Sort_Component-300x206.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Next, we place and configure the Merge Join component. Here, the join type is set to left outer join (as we want to select all data from the source table), the join is configured between Item_SKU columns only, all columns are selected from tbl_Source and finally only one column &#8211; Item_SKU &#8211; is selected from tbl_Destination table, which we also rename to give it a more distinct alias. All these steps are highlighted in the image below.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_mergejoin_component\/\" rel=\"attachment wp-att-566\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-566\" title=\"SSIS_Incremental_Tbl_Update_MergeJoin_Component\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_MergeJoin_Component.png\" alt=\"\" width=\"580\" height=\"644\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Once Merge Join has been configured, we use Conditional Split component to segregate the data. All we really need to do here is to specify the condition which will allow this transform to pull out the records which do not exist in tbl_Destination. These records have been qualified as SKU_ISNULL in the Merge Join component in the previous transform. To do this, we use ISNULL(SKU_ISNULL) statement and give the output a name, in this case it\u2019s \u2018New_Data\u2019.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_cs_component\/\" rel=\"attachment wp-att-571\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-571\" title=\"SSIS_Incremental_Tbl_Update_CS_Component\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_CS_Component.png\" alt=\"\" width=\"580\" height=\"400\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Finally, we create an OLE DB Destination container and when linking it to the Conditional Split transform, we select \u2018New_Data\u2019 (or whatever name we used to describe the data difference) from the drop-down box as per below.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/bicortex.com\/incremental-table-update-using-ssis\/ssis_incremental_tbl_update_destination_component\/\" rel=\"attachment wp-att-574\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-574\" title=\"SSIS_Incremental_Tbl_Update_Destination_Component\" src=\"http:\/\/bicortex.com\/bicortex\/wp-content\/post_content\/\/2012\/02\/SSIS_Incremental_Tbl_Update_Destination_Component.png\" alt=\"\" width=\"580\" height=\"345\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">As the last step we map the outputs from conditional split with the column names from tbl_Destination.<\/p>\n<p style=\"text-align: justify;\">The same result can be achieved using other methods. For example, sticking to SSIS and BIDS we can use Execute SQL Task control flow component with the following query:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nINSERT INTO tbl_Destination\r\n(Item_SKU,Item_Name,Item_Category,Item_Price,Item_Availability_Flag,Item_Discount_Flag)\r\nSELECT * FROM tbl_Source\r\nEXCEPT \r\nSELECT * FROM tbl_Destination\r\nGO\r\n<\/pre>\n<p style=\"text-align: justify;\">Alternatively, we can issue a simple update statement which will do the trick just as nicely. Whichever method rocks your boat, this is just one of them and given some further customizations it can be quite effective in comparison to using simple \u2018UPDATE\u2019 or \u2018INSERT with EXCEPT\u2019. For example we can isolate the new data (tables difference) and do some further processing or transformations which would be cumbersome using SQL only.   <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post I will demonstrate how to update a table (let\u2019s call it a destination table) with data from another table (let\u2019s call this one source table) based on the differences between the two via a SQL Server Integration Services package. This exercise can achieve the same result through a number of different implementation [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[50],"tags":[12,49,13],"class_list":["post-529","post","type-post","status-publish","format-standard","hentry","category-ssis","tag-code","tag-sql","tag-ssis"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/529","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/comments?post=529"}],"version-history":[{"count":50,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/529\/revisions"}],"predecessor-version":[{"id":689,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/posts\/529\/revisions\/689"}],"wp:attachment":[{"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/media?parent=529"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/categories?post=529"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bicortex.com\/bicortex\/wp-json\/wp\/v2\/tags?post=529"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}