How to Handle Evolving Database Schemas in your ETL with Azure Data Factory

Published Apr 13 2020 03:14 PM 5,360 Views
Microsoft

When transforming data in ADF with Azure SQL Database, you have the choice of enforcing a validated schema or invoking "schema drift". If you have a scenario where your source or sink database schemas will change over time, you may wish to build your data flows in a way that incorporates flexible schema patterns. The features that we'll use in this post to demonstrate this technique include schema drift, column patterns, late binding, and auto-mapping.

 

 

Late Binding

Start with a new data flow and add an Azure SQL Database source dataset. Make sure your dataset does not import the schema and that your source has no projection. This is key to allow your flows to use "late binding" for database schemas that change.

 

Schema Drift

On both the Source and Sink transformations set "Schema Drift" on so that ADF will allow any columns to flow through, regardless of their "early binding" definitions in the dataset of projection. In this scenario, we're not including any schema or projection, so schema drift is needed. If you have a scenario that requires hardened schemas, set "Validate Schema" and import the schema in the dataset and set a source projection.

 

Column Patterns

When you are working with flexible schemas and schema drift, avoid naming specific column names in your data flow metadata. When transforming data and writing Derived Column expressions, use "column patterns". You will look for matching names, types, ordinal position, data types, and combinations of those field characteristics to transform data with flexible schemas.

 

flex4.png

 

Auto-Mapping

On the Sink transformation, map your incoming to outgoing fields using "auto-mapping". Setting specific hardened mappings is "early binding" and here you wish to remain flexible with "late binding".

 

One last note: In the video above, I demonstrate using the Alter Row transformation to update existing database rows. When using full schema-less datasets, you must enter the primary key fields in your sink using Dynamic Content. Simply refer to the target database key columns as string column names:

 

flex3.png

 

11 Comments
%3CLINGO-SUB%20id%3D%22lingo-sub-1303851%22%20slang%3D%22en-US%22%3EHow%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1303851%22%20slang%3D%22en-US%22%3E%3CP%3EWhen%20transforming%20data%20in%20ADF%20with%20Azure%20SQL%20Database%2C%20you%20have%20the%20choice%20of%20enforcing%20a%20validated%20schema%20or%20invoking%20%22schema%20drift%22.%20If%20you%20have%20a%20scenario%20where%20your%20source%20or%20sink%20database%20schemas%20will%20change%20over%20time%2C%20you%20may%20wish%20to%20build%20your%20data%20flows%20in%20a%20way%20that%20incorporates%20flexible%20schema%20patterns.%20The%20features%20that%20we'll%20use%20in%20this%20post%20to%20demonstrate%20this%20technique%20include%20schema%20drift%2C%20column%20patterns%2C%20late%20binding%2C%20and%20auto-mapping.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3C%2FP%3E%3CDIV%20class%3D%22video-embed-center%20video-embed%22%3E%3CIFRAME%20class%3D%22embedly-embed%22%20src%3D%22https%3A%2F%2Fcdn.embedly.com%2Fwidgets%2Fmedia.html%3Fsrc%3Dhttps%253A%252F%252Fwww.youtube.com%252Fembed%252FurzLAb83IjU%253Ffeature%253Doembed%26amp%3Bdisplay_name%3DYouTube%26amp%3Burl%3Dhttps%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DurzLAb83IjU%26amp%3Bimage%3Dhttps%253A%252F%252Fi.ytimg.com%252Fvi%252FurzLAb83IjU%252Fhqdefault.jpg%26amp%3Bkey%3Dfad07bfa4bd747d3bdea27e17b533c0e%26amp%3Btype%3Dtext%252Fhtml%26amp%3Bschema%3Dyoutube%22%20width%3D%22400%22%20height%3D%22225%22%20scrolling%3D%22no%22%20title%3D%22YouTube%20embed%22%20frameborder%3D%220%22%20allow%3D%22autoplay%3B%20fullscreen%22%20allowfullscreen%3D%22true%22%3E%3C%2FIFRAME%3E%3C%2FDIV%3E%3CP%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CU%3E%3CSTRONG%3ELate%20Binding%3C%2FSTRONG%3E%3C%2FU%3E%3C%2FP%3E%0A%3CP%3EStart%20with%20a%20new%20data%20flow%20and%20add%20an%20Azure%20SQL%20Database%20source%20dataset.%20Make%20sure%20your%20dataset%20does%20not%20import%20the%20schema%20and%20that%20your%20source%20has%20no%20projection.%20This%20is%20key%20to%20allow%20your%20flows%20to%20use%20%22late%20binding%22%20for%20database%20schemas%20that%20change.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CU%3E%3CSTRONG%3ESchema%20Drift%3C%2FSTRONG%3E%3C%2FU%3E%3C%2FP%3E%0A%3CP%3E%3CU%3E%3C%2FU%3EOn%20both%20the%20Source%20and%20Sink%20transformations%20set%20%22Schema%20Drift%22%20on%20so%20that%20ADF%20will%20allow%20any%20columns%20to%20flow%20through%2C%20regardless%20of%20their%20%22early%20binding%22%20definitions%20in%20the%20dataset%20of%20projection.%20In%20this%20scenario%2C%20we're%20not%20including%20any%20schema%20or%20projection%2C%20so%20schema%20drift%20is%20needed.%20If%20you%20have%20a%20scenario%20that%20requires%20hardened%20schemas%2C%20set%20%22Validate%20Schema%22%20and%20import%20the%20schema%20in%20the%20dataset%20and%20set%20a%20source%20projection.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CU%3E%3CSTRONG%3EColumn%20Patterns%3C%2FSTRONG%3E%3C%2FU%3E%3C%2FP%3E%0A%3CP%3E%3CU%3E%3C%2FU%3EWhen%20you%20are%20working%20with%20flexible%20schemas%20and%20schema%20drift%2C%20avoid%20naming%20specific%20column%20names%20in%20your%20data%20flow%20metadata.%20When%20transforming%20data%20and%20writing%20Derived%20Column%20expressions%2C%20use%20%22column%20patterns%22.%20You%20will%20look%20for%20matching%20names%2C%20types%2C%20ordinal%20position%2C%20data%20types%2C%20and%20combinations%20of%20those%20field%20characteristics%20to%20transform%20data%20with%20flexible%20schemas.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22flex4.png%22%20style%3D%22width%3A%20488px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F183856i209057D082E065B7%2Fimage-dimensions%2F488x182%3Fv%3D1.0%22%20width%3D%22488%22%20height%3D%22182%22%20title%3D%22flex4.png%22%20alt%3D%22flex4.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CU%3E%3CSTRONG%3EAuto-Mapping%3C%2FSTRONG%3E%3C%2FU%3E%3C%2FP%3E%0A%3CP%3EOn%20the%20Sink%20transformation%2C%20map%20your%20incoming%20to%20outgoing%20fields%20using%20%22auto-mapping%22.%20Setting%20specific%20hardened%20mappings%20is%20%22early%20binding%22%20and%20here%20you%20wish%20to%20remain%20flexible%20with%20%22late%20binding%22.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EOne%20last%20note%3A%20In%20the%20video%20above%2C%20I%20demonstrate%20using%20the%20Alter%20Row%20transformation%20to%20update%20existing%20database%20rows.%20When%20using%20full%20schema-less%20datasets%2C%20you%20must%20enter%20the%20primary%20key%20fields%20in%20your%20sink%20using%20Dynamic%20Content.%20Simply%20refer%20to%20the%20target%20database%20key%20columns%20as%20string%20column%20names%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22flex3.png%22%20style%3D%22width%3A%20558px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F183855iAC099B121BC83A96%2Fimage-dimensions%2F558x269%3Fv%3D1.0%22%20width%3D%22558%22%20height%3D%22269%22%20title%3D%22flex3.png%22%20alt%3D%22flex3.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1303851%22%20slang%3D%22en-US%22%3E%3CP%3EAzure%20Data%20Factory%20supports%20a%20number%20of%20built-in%20features%20to%20enable%20flexible%20ETL%20jobs%20that%20can%20evolve%20with%20your%20database%20schemas.%20In%20this%20blog%20post%2C%20I%20show%20you%20how%20to%20leverage%20data%20flow%20schema%20drift%20capabilities%20for%20flexible%20schema%20handling%20with%20Azure%20SQL%20DB.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22flex4.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F183856i209057D082E065B7%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22flex4.png%22%20alt%3D%22flex4.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1303851%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20Data%20Factory%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%20ETL%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EMapping%20Data%20Flows%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1304444%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1304444%22%20slang%3D%22en-US%22%3E%3CP%3EOne%20addition%20Mark%3A%20this%20is%20all%20focussed%20on%20Data%20Flows.%20For%20the%20Copy%20activity%20as%20long%20as%20the%20data%20set%20and%20the%20copy%20activity%20no%20schema%20have%20defined%2C%20the%20copy%20activity%20will%20do%20a%20auto-mapping%20based%20on%20name.%20Simple%20and%20effective.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EOne%20interesting%20note%3B%20the%20auto-mapping%20is%20case%20sensitive.%20ADF%20will%20even%20warn%20if%20there%20was%20no%20match%2C%20but%20there%20was%20a%20match%20on%20different%20casing.%20I%20like%20that%20message%2C%20there%20is%20a%20problem%20and%20at%20the%20same%20time%20ADF%20flags%20what%20the%20likely%20cause%20is.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1304449%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1304449%22%20slang%3D%22en-US%22%3E%3CP%3ENote%20that%20my%20example%20is%20ETL.%20I%20am%20transforming%20and%20updating%20rows%2C%20not%20just%20simple%20mapping.%20That's%20why%20this%20needs%20to%20be%20done%20in%20a%20Data%20Flow.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1318645%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1318645%22%20slang%3D%22en-US%22%3E%3CP%3EUnfortunately%2C%20ADF%20is%20still%20quite%20immature.%20For%20example%2C%20Greenplum%20connector%20does%20not%20recognize%20data%20types%20properly%2C%20posrgresql%20connector%20cannot%20use%20passwords%20with%20special%20characters...%20Issue%20tracker%20for%20ADF%20on%20GitHub%20is%20dead.%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1327283%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1327283%22%20slang%3D%22en-US%22%3E%3CP%3EI%20would%20like%20to%20see%20the%20same%20demo%20but%20have%20data%20flow%20create%20the%20target%20table%20schema%20columns%20via%20the%20schema%20drift.%20This%20only%20demonstrates%20a%20target%20table%20with%20the%20schema%20existing.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1327354%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1327354%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F628537%22%20target%3D%22_blank%22%3E%40craigwhite%3C%2FA%3E%26nbsp%3BAll%20you%20have%20to%20do%20is%20set%20%22recreate%20table%22%20on%20the%20sink%20and%20ADF%20will%20create%20the%20target%20table%20with%20your%20incoming%20columns%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1327599%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1327599%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F175989%22%20target%3D%22_blank%22%3E%40Mark%20Kromer%3C%2FA%3E%26nbsp%3BWill%20recreating%20the%20table%20delete%20all%20existing%20data%3F%20I%20was%20hoping%20if%20a%20new%20column%5Cs%20was%20created%20on%20the%20source%20table%2C%20the%20new%20column%5Cs%20would%20be%20added%20to%20the%20target%20table%20without%20data%20disruption%20(table%20alter).%20Is%20this%20the%20case%3F%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1327906%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1327906%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F628537%22%20target%3D%22_blank%22%3E%40craigwhite%3C%2FA%3E%26nbsp%3B%20It%20is%20a%20drop%2Frecreate%20of%20the%20table%2C%20not%20an%20alter%20table%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1369785%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1369785%22%20slang%3D%22en-US%22%3E%3CP%3EIs%20there%20a%20way%20to%20alter%20table%20and%20not%20recreate%20table%3F%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1921815%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1921815%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F175989%22%20target%3D%22_blank%22%3E%40Mark%20Kromer%3C%2FA%3E%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHi%20Mark%2C%20We%20have%20set%20of%20500%20CSV%20files%20which%20we%20have%20uploaded%20to%20Azure%20storage%20container.%20These%20CSV%20files%20have%204%20different%20schemas%20being%20used%20with%20few%20columns%20common%20and%20few%20columns%20different.%20Our%20objective%20is%20to%20build%20a%20pipeline%20to%20load%20all%20these%20files%20into%20a%20single%20SQL%20database%20by%20mapping%20relevant%20columns%20for%20each%20schema.%20We%20have%20tried%20using%20schema%20drift%20and%20it%20is%20not%20giving%20required%20results.%20Any%20ideas%20on%20how%20we%20can%20do%20this%20please.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThanks.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1967144%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1967144%22%20slang%3D%22en-US%22%3E%3CP%3EHi%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F175989%22%20target%3D%22_blank%22%3E%40Mark%20Kromer%3C%2FA%3E%3C%2FP%3E%3CP%3Esome%20comments%20before%20you%20wrote%3A%3CBR%20%2F%3E%22It%20is%20a%20drop%2Frecreate%20of%20the%20table%2C%20not%20an%20alter%20table.%22%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3Eis%20there%20a%20way%20to%20alter%20the%20table%20and%20add%20the%20missing%20columns%3F%3CBR%20%2F%3Ethis%20would%20be%20a%20very%20useful%20function%2C%20because%20we%20have%20sources%20whose%20structure%20can%20change%2C%20but%20we%20do%20not%20want%20to%20manually%20change%20the%20target%20tables%20every%20time.%20in%20principle%3A%20if%20columns%20are%20missing%2C%20create%20them%20automatically%20without%20losing%20data.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2053995%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Handle%20Evolving%20Database%20Schemas%20in%20your%20ETL%20with%20Azure%20Data%20Factory%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2053995%22%20slang%3D%22en-US%22%3E%3CP%3EHi%20Mark%2C%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EGreat%20video!%20Thanks%20for%20it.%20Is%20it%20possible%20to%20do%20an%20aggregate%20transformation%20in%20this%20case%20when%20we%20don't%20have%20schema%20input%3F%20I'm%20having%20multiples%20source%20tables%20as%20parameters%20%22tableName%22.%20I%20would%20like%20to%20union%20them%20and%20group%20by%20after.%20I%20tried%20to%20use%20the%20aggregation%20but%20it%20does%20not%20show%20any%20column%20name%20for%20the%20group%20by%20part.%20I%20tried%20to%20use%20%22%3CSPAN%3Ename%26nbsp%3B%3C%2FSPAN%3E%3CSPAN%3E%3D%3D%3C%2FSPAN%3E%3CSPAN%3E%26nbsp%3BmycolumName%3C%2FSPAN%3E%3CSPAN%3E%22%20but%20does%20not%20work%20there.%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%3CSPAN%3EThank%20you.%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E
Version history
Last update:
‎Apr 13 2020 03:14 PM
Updated by: