From 741deee3e4643be4ba9b60815716168ed0505ae6 Mon Sep 17 00:00:00 2001 From: Rashmi Shukla Date: Sun, 12 Sep 2021 18:24:09 +0000 Subject: [PATCH] Deleted Azure DW Load Scripts --- .../CTASLoad-Example.sql | 63 ------ .../GenerateLoadScript-V1.sql | 165 --------------- .../GenerateLoadScript-V2.sql | 195 ------------------ ...erateLoadScript-V3-ContainerSubfolders.sql | Bin 22994 -> 0 bytes .../Azure SQL DW Load Script Files/README.md | 33 --- .../MICROSOFT LICENSE TERMS.docx | Bin 20569 -> 0 bytes Azure DW Load Scripts/READ ME.docx | Bin 23232 -> 0 bytes Azure DW Load Scripts/readme.md | 1 - 8 files changed, 457 deletions(-) delete mode 100644 Azure DW Load Scripts/Azure SQL DW Load Script Files/CTASLoad-Example.sql delete mode 100644 Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V1.sql delete mode 100644 Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V2.sql delete mode 100644 Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V3-ContainerSubfolders.sql delete mode 100644 Azure DW Load Scripts/Azure SQL DW Load Script Files/README.md delete mode 100644 Azure DW Load Scripts/MICROSOFT LICENSE TERMS.docx delete mode 100644 Azure DW Load Scripts/READ ME.docx delete mode 100644 Azure DW Load Scripts/readme.md diff --git a/Azure DW Load Scripts/Azure SQL DW Load Script Files/CTASLoad-Example.sql b/Azure DW Load Scripts/Azure SQL DW Load Script Files/CTASLoad-Example.sql deleted file mode 100644 index e83f4b3..0000000 --- a/Azure DW Load Scripts/Azure SQL DW Load Script Files/CTASLoad-Example.sql +++ /dev/null @@ -1,63 +0,0 @@ -/***This Artifact belongs to the Data SQL Ninja Engineering Team***/ --- STEP 1: Create a master key. Only necessary if one does not already exist. -CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MyUltraSecurePassword!12345!'; -GO - --- STEP 2: Create a database scoped credential --- Azure Data Lake Credential -CREATE DATABASE SCOPED CREDENTIAL AzureCredential -WITH IDENTITY = '@https://login.microsoftonline.com//oauth2/token', - SECRET = ''; - -/* Blob Storage Credential -CREATE DATABASE SCOPED CREDENTIAL AzureCredential -WITH IDENTITY = 'SHARED ACCESS SIGNATURE', - SECRET = 'your key here'; -*/ - --- STEP 3: Create an external data source - type HADOOP for ADLS -CREATE EXTERNAL DATA SOURCE AzureStorage -WITH (TYPE = HADOOP, LOCATION = 'adl://.azuredatalakestore.net', CREDENTIAL = AzureCredential); -GO - -/* Blob Storage Data Source - wabs syntax with Hadoop type -CREATE EXTERNAL DATA SOURCE AzureStorage -WITH (TYPE = HADOOP, LOCATION = 'wasbs://container@storageacct.blob.core.windows.net', - CREDENTIAL = AzureCredential); -*/ - --- STEP 4: Create an external file format -CREATE EXTERNAL FILE FORMAT TextFileFormat -WITH (FORMAT_TYPE = DELIMITEDTEXT, FORMAT_OPTIONS - (FIELD_TERMINATOR = '0x01', STRING_DELIMITER = '"', -- DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss.fff', - USE_TYPE_DEFAULT = FALSE), - DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec' - ); -GO - --- STEP 5: Create external table pointing to blob storage files -CREATE EXTERNAL TABLE [ext_ACCOUNT_FACT] -( - [ACCT_PK_ID] bigint NOT NULL, - [PERSON_PK_ID] bigint NOT NULL, - [SALES_PERSON_PK_ID] int NOT NULL, - [BATCH_ID] bigint NULL, - [START_TMSP] datetime NULL, - [END_TMSP] datetime NULL, - [ACCT_NAME] varchar(50) NULL, - [ACCT_FLAG] varchar(2) NULL, - [ACCT_STATUS] varchar(24) NULL, - [ACCT_STATUS_CHG_DATE] datetime NULL, - [ACCT_TYPE_CODE] varchar(30) NULL -) -WITH ( LOCATION='/data/test/', DATA_SOURCE = AzureStorage, FILE_FORMAT = TextFileFormat, REJECT_TYPE = VALUE, REJECT_VALUE = 0 ); -GO - --- STEP 6: Create Table As Select (CTAS) operation - invokes Polybase to pull information out of one or more text files in ADLS into DW tables --- note you need to split the input text files to take advantage of parallel load on the compute nodes -CREATE TABLE [POC_DM].[ACCOUNT_FACT] -WITH (DISTRIBUTION = HASH([ACCT_PK_ID])) -AS SELECT * FROM ext_ACCOUNT_FACT -OPTION (LABEL = 'CTAS : Load ACCOUNT_FACT'); -GO - diff --git a/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V1.sql b/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V1.sql deleted file mode 100644 index 345b1f1..0000000 --- a/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V1.sql +++ /dev/null @@ -1,165 +0,0 @@ -/***This Artifact belongs to the Data SQL Ninja Engineering Team***/ -declare @sourceschema varchar(128) = 'SRC_POC_DM' -declare @targetschema varchar(128) = 'TARG_POC_DM' -declare @blobstore varchar(100) = '.blob.core.windows.net' - -set nocount on - --- ensure your data warehouse has a master key --- CREATE MASTER KEY; - --- Use your blob storage key to provide SQL DW access to blob storage -if not exists(select * from [sys].[database_credentials] where [name]='AzureStorageCredential') - CREATE DATABASE SCOPED CREDENTIAL AzureStorageCredential WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = 'your key here...==' - --- Create the file format definition -if not exists(select * from [sys].[external_file_formats] where [name]='TextFileFormat') - CREATE EXTERNAL FILE FORMAT TextFileFormat WITH (FORMAT_TYPE = DELIMITEDTEXT, FORMAT_OPTIONS (FIELD_TERMINATOR = '0x01', --STRING_DELIMITER = '', - USE_TYPE_DEFAULT = FALSE), DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec') - -declare @objectid int, @table varchar(128), @colid int, @column varchar(128), @type varchar(128), @length smallint, @precision tinyint, @scale tinyint, @nullable bit, @colstr varchar(150) -declare @cmd varchar(max), @distcol varchar(128), @disttype varchar(50) -declare @trows int = 0, @trow int = 1, @crows int = 0, @crow int = 1, @start datetime, @tblrows bigint - --- Ensure target schema exists -if not exists(select * from sys.schemas where name = @targetschema) - begin - select @cmd = 'CREATE SCHEMA ' + @targetschema - exec(@cmd) - end - --- Check external table schema exists -if not exists(select * from sys.schemas where name = 'ASB') - exec('CREATE SCHEMA ASB') - --- cleanup of any previous failed run -IF OBJECT_ID('tempdb..#tables') IS NOT NULL - DROP TABLE #tables -IF OBJECT_ID('tempdb..#columns') IS NOT NULL - DROP TABLE #columns - -create table #tables -( - rowid int not null, - objectid int not null, - [table] varchar(128) not null -) -WITH ( HEAP , DISTRIBUTION = ROUND_ROBIN ) - -create table #columns -( - colid int, - [column] varchar(128), - [type] varchar(128), - [length] smallint, - [precision] tinyint, - [scale] tinyint, - [nullable] bit -) -WITH ( HEAP , DISTRIBUTION = ROUND_ROBIN ) - --- Set up to process all tables in the defined source schema -insert into #tables -select row_number() over (order by tb.name), object_id, tb.name -from sys.tables tb join sys.schemas s on (tb.schema_id=s.schema_id) -where s.name = @sourceschema - -select @trows = count(*) from #tables - ---select * from #tables - --- initial cleanup of any previous run - if an external table still exists, you will have to drop it first -if exists(select * from sys.external_data_sources where name='AzureStorage') - drop external data source AzureStorage - -select @objectid=objectid, @table=[table] from #tables where rowid=@trow - -while (@trow <= @trows) - begin - select @start = getdate() -- save start time - print '---------------------- ' + @targetschema + '.' + @table + ' ----------------------' - - -- create the external data source - select @cmd = 'CREATE EXTERNAL DATA SOURCE AzureStorage WITH (TYPE = HADOOP, LOCATION = ''wasbs://' + replace(lower(@table), '_', '-') + '@' + @blobstore + ''', CREDENTIAL = AzureStorageCredential);' - print @cmd - print '' - exec(@cmd) - - -- clear all rows in columns temp table (for previous table) - truncate table #columns - - -- get all the column definitions for the target table - insert into #columns - select c.column_id, c.[name], t.[name], c.max_length, c.[precision], c.scale, c.is_nullable - from sys.columns c - join sys.types t on (c.user_type_id=t.user_type_id) - where object_id = @objectid - order by c.column_id - - -- build external table definition - select @cmd = 'CREATE EXTERNAL TABLE [ASB].[' + @table + '] (' - - -- process each column for the target table - select @crows = count(*) from #columns - select @crow = 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - while (@crow <= @crows) - begin - if (@colid <> 1) select @cmd = @cmd + ', ' - select @cmd = @cmd + '[' + @column + '] ' + @type - if @type in ('char', 'varchar', 'nchar', 'nvarchar') - select @cmd = @cmd + '(' + case when @length < 0 then 'max' else cast(@length as varchar(4)) end + ')' - else if @type in ('numeric', 'decimal', 'real', 'float') - select @cmd = @cmd + '(' + cast(@precision as varchar(3)) + case when @type in ('decimal', 'numeric') then ', ' + cast(@scale as varchar(3)) else '' end + ')' - else if @type = 'datetime2' - select @cmd = @cmd + '(' + cast(@scale as varchar(3)) + ')' - select @cmd = @cmd + case when @nullable then ' NULL' else ' NOT NULL' end - select @crow = @crow + 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - end - select @cmd = @cmd + ') WITH ( LOCATION=''./'', DATA_SOURCE = AzureStorage, FILE_FORMAT = TextFileFormat, REJECT_TYPE = VALUE, REJECT_VALUE = 0 );' - declare @i int = 1 - while (@i < len(@cmd)) - begin - print substring(@cmd, @i, 1000) -- statements can exceed the capacity of a single print - select @i = @i + 1000 - end - print '' - exec(@cmd) - - -- get the distribution mechanism and column for the target table - select @distcol='', @disttype=distribution_policy_desc from sys.pdw_table_distribution_properties where object_id=@objectid - select @distcol=c.[name] from sys.pdw_column_distribution_properties d join sys.columns c on (d.object_id=c.object_id and d.column_id=c.column_id) where d.[object_id]=@objectid and distribution_ordinal=1 - - -- remove target table if it already exists - if exists(select * from sys.tables t join sys.schemas s on (t.schema_id=s.schema_id) where s.[name] = @targetschema and t.[name]=@table) - begin - select @cmd = 'DROP TABLE [' + @targetschema + '].[' + @table + ']' - exec(@cmd) - end - - -- build simple CTAS statement (since column type and nullability done in external table) - select @cmd = 'CREATE TABLE [' + @targetschema + '].[' + @table + '] WITH (DISTRIBUTION = '+ case when ISNULL(@disttype, '') = '' then 'HEAP' else @disttype end + case when @distcol != '' then '([' + @distcol + '])' else '' end + - ') AS SELECT * FROM [ASB].[' + @table + '] OPTION (LABEL = ''CTAS : Load [' + @targetschema + '].[' + @table + ']'');' - print @cmd - print '' - exec(@cmd) - - -- Cleanup external objects - select @cmd = 'DROP EXTERNAL TABLE [ASB].[' + @table + ']' - print @cmd - exec(@cmd) - - print 'DROP EXTERNAL DATA SOURCE AzureStorage' - DROP EXTERNAL DATA SOURCE AzureStorage - - -- Output row count and elapsed load time for the current table - select @cmd = 'select COUNT_BIG(*) as ''Rows in [' + @targetschema + '].[' + @table + ']'', ' + cast(datediff(s, @start, getdate())/60.0 as varchar(40)) + ' as ''Minutes to Load'' from [' + @targetschema + '].[' + @table + ']' - exec(@cmd) - - -- Increment to the next table - select @trow = @trow + 1 - select @objectid=objectid, @table=[table] from #tables where rowid=@trow - end -drop table #tables -drop table #columns diff --git a/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V2.sql b/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V2.sql deleted file mode 100644 index e8336ea..0000000 --- a/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V2.sql +++ /dev/null @@ -1,195 +0,0 @@ -/***This Artifact belongs to the Data SQL Ninja Engineering Team***/ -declare @sourceschema varchar(128) = 'SRC_POC_DM' -declare @targetschema varchar(128) = 'TARG_POC_DM' -declare @blobstore varchar(100) = '.blob.core.windows.net' - -set nocount on - --- ensure your data warehouse has a master key --- CREATE MASTER KEY; - --- Use your blob storage key to provide SQL DW access to blob storage -if not exists(select * from [sys].[database_credentials] where [name]='AzureStorageCredential') - CREATE DATABASE SCOPED CREDENTIAL AzureStorageCredential WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = 'your key here...==' - --- Create the file format definition -if not exists(select * from [sys].[external_file_formats] where [name]='TextFileFormat') - CREATE EXTERNAL FILE FORMAT TextFileFormat WITH (FORMAT_TYPE = DELIMITEDTEXT, FORMAT_OPTIONS (FIELD_TERMINATOR = '0x01', --STRING_DELIMITER = '', - USE_TYPE_DEFAULT = FALSE), DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec') - -declare @objectid int, @table varchar(128), @colid int, @column varchar(128), @type varchar(128), @length smallint, @precision tinyint, @scale tinyint, @nullable bit, @colstr varchar(150) -declare @cmd varchar(max), @distcol varchar(128), @disttype varchar(50) -declare @trows int = 0, @trow int = 1, @crows int = 0, @crow int = 1, @start datetime, @tblrows bigint - --- Ensure target schema exists -if not exists(select * from sys.schemas where name = @targetschema) - begin - select @cmd = 'CREATE SCHEMA ' + @targetschema - exec(@cmd) - end --- Check external table schema exists -if not exists(select * from sys.schemas where name = 'ASB') - exec('CREATE SCHEMA ASB') - --- cleanup of any previous failed run -IF OBJECT_ID('tempdb..#tables') IS NOT NULL - DROP TABLE #tables -IF OBJECT_ID('tempdb..#columns') IS NOT NULL - DROP TABLE #columns - -create table #tables -( - rowid int not null, - objectid int not null, - [table] varchar(128) not null -) -WITH ( HEAP , DISTRIBUTION = ROUND_ROBIN ) - -create table #columns -( - colid int, - [column] varchar(128), - [type] varchar(128), - [length] smallint, - [precision] tinyint, - [scale] tinyint, - [nullable] bit -) -WITH ( HEAP , DISTRIBUTION = ROUND_ROBIN ) - --- Set up to process all tables in the defined source schema -insert into #tables -select row_number() over (order by tb.name), object_id, tb.name -from sys.tables tb join sys.schemas s on (tb.schema_id=s.schema_id) -where s.name = @sourceschema - -select @trows = count(*) from #tables - ---select * from #tables - --- initial cleanup of any previous run - if an external table still exists, you will have to drop it first -if exists(select * from sys.external_data_sources where name='AzureStorage') - drop external data source AzureStorage - -select @objectid=objectid, @table=[table] from #tables where rowid=@trow - -while (@trow <= @trows) - begin - select @start = getdate() -- save start time - print '---------------------- ' + @targetschema + '.' + @table + ' ----------------------' - - -- create the external data source - select @cmd = 'CREATE EXTERNAL DATA SOURCE AzureStorage WITH (TYPE = HADOOP, LOCATION = ''wasbs://' + replace(lower(@table), '_', '-') + '@' + @blobstore + ''', CREDENTIAL = AzureStorageCredential);' - print @cmd - print '' - exec(@cmd) - - -- clear all rows in columns temp table (for previous table) - truncate table #columns - - -- get all the column definitions for the target table - insert into #columns - select c.column_id, c.[name], t.[name], c.max_length, c.[precision], c.scale, c.is_nullable - from sys.columns c - join sys.types t on (c.user_type_id=t.user_type_id) - where object_id = @objectid - order by c.column_id - - -- build external table definition - select @cmd = 'CREATE EXTERNAL TABLE [ASB].[' + @table + '] (' - - -- process each column for the target table - select @crows = count(*) from #columns - select @crow = 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - while (@crow <= @crows) - begin - if (@colid <> 1) select @cmd = @cmd + ',' - select @cmd = @cmd + '[' + @column + '] ' + case when @type in ('nvarchar', 'nchar') then 'nvarchar' else 'varchar' end + '(' + - case when @type in ('decimal', 'numeric', 'bigint', 'real', 'float', 'money') then '35' - when @type in ('int', 'smallmoney') then '14' - when @type in ('bit', 'tinyint', 'smallint') then '6' - when @type in ('char', 'varchar', 'nchar', 'nvarchar', 'binary', 'varbinary') then case when @length = -1 then 'MAX' when @length < 6 then '10' when @length > 3980 and left(@type,1)='n' then '4000' when @length > 7980 then '8000' else cast(@length+20 as varchar(5)) end -- handle null and add quotes (& embedded quotes) - when @type = 'uniqueidentifier' then '38' - else '50' end + ') NULL' -- dates and times @ 50 - image, text, xml, hierarchy and spatial data types not supported on DW - select @crow = @crow + 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - end - select @cmd = @cmd + ') WITH ( LOCATION=''./'', DATA_SOURCE = AzureStorage, FILE_FORMAT = TextFileFormat, REJECT_TYPE = VALUE, REJECT_VALUE = 0 );' - declare @i int = 1 - while (@i < len(@cmd)) - begin - print substring(@cmd, @i, 1000) -- statements can exceed the capacity of a single print - select @i = @i + 1000 - end - print '' - exec(@cmd) - - -- get the distribution mechanism and column for the target table - select @distcol='', @disttype=distribution_policy_desc from sys.pdw_table_distribution_properties where object_id=@objectid - select @distcol=c.[name] from sys.pdw_column_distribution_properties d join sys.columns c on (d.object_id=c.object_id and d.column_id=c.column_id) where d.[object_id]=@objectid and distribution_ordinal=1 - - -- remove target table if it already exists - if exists(select * from sys.tables t join sys.schemas s on (t.schema_id=s.schema_id) where s.[name] = @targetschema and t.[name]=@table) - begin - select @cmd = 'DROP TABLE [' + @targetschema + '].[' + @table + ']' - exec(@cmd) - end - - -- build CTAS statement - looping through all of the columns to do a cast to the appropriate data type - select @cmd = 'CREATE TABLE [' + @targetschema + '].[' + @table + '] WITH (DISTRIBUTION = '+ case when ISNULL(@disttype, '') = '' then 'HEAP' else @disttype end + case when @distcol != '' then '([' + @distcol + '])' else '' end + ') AS SELECT ' - select @crow = 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - while (@crow <= @crows) - begin - select @colstr = 'substring(['+@column+'], 2, LEN(['+@column+'])-2)' -- remove lead and tail quotes - if (@colid <> 1) select @cmd = @cmd + ', ' - if (@nullable = 0) -- if this column is not nullable we have to give SQL DW the hint to make it NOT NULL - in theory we should error if there is a text value of null in the field, but that is just more code... - select @cmd = @cmd + 'ISNULL((' - if @type in ('char', 'varchar', 'nchar', 'nvarchar') -- remove escaped quotes and replace special line end characters with line feed - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null else cast(replace(replace(replace(' + @colstr + ', ''\"'', ''"''), char(31), char(10)), char(30), char(13)) as '+ @type +'('+ case when @length=-1 then 'max' else cast(@length as varchar(10)) end +')) end' + case when @nullable=0 then '), '''')' else '' end - else if @type in ('numeric', 'decimal') - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null else cast(' + @colstr + ' as ' + @type + '(' + cast(@precision as varchar(3)) + ',' + cast(@scale as varchar(3)) + ')) end' + case when @nullable=0 then '), 0.)' else '' end - else if @type in ('bigint', 'real', 'float', 'money', 'int', 'smallmoney', 'bit', 'tinyint', 'smallint') - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null else cast(' + @colstr + ' as ' + @type + ') end' + case when @nullable=0 then '), 0)' else '' end - else if @type in ('datetime', 'smalldatetime', 'date') - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null when left(['+@column+'], 5) < ''"1753'' then cast(''1753-01-01 00:00:00'' as ' + @type + ') else cast(substring(' + @colstr + ', 1, (case when CHARINDEX(''.'', ' + @column + ') != 0 then CHARINDEX(''.'', ' + @column + ') else len(' + @column + ') end)-2) as ' + @type + ') end' + case when @nullable=0 then '), cast(''1753-01-01 00:00:00'' as ' + @type + '))' else '' end - else if @type = 'date' - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null when left(['+@column+'], 5) < ''"0001'' then cast(''0001-01-01'' as date) else cast(' + @colstr + ' as date) end' + case when @nullable=0 then '), cast(''0001-01-01'' as date))' else '' end - else if @type = 'datetime2' - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null when left(['+@column+'], 5) < ''"0001'' then cast(''0001-01-01 00:00:00'' as datetime2(' + cast(@scale as varchar(3)) + ')) else cast(' + @colstr + ' as datetime2(' + cast(@scale as varchar(3)) + ')) end' + case when @nullable=0 then '), cast(''0001-01-01 00:00:00'' as datetime2(' + @precision + ')))' else '' end - else if @type = 'uniqueidentifier' - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null else cast(' + @colstr + ' as ' + @type + ') end' + case when @nullable=0 then '), cast(''00000000-0000-0000-0000-000000000000'' as uniqueidentifier))' else '' end - else -- not sure any data types are left - if so, you need a null value for 'not null' instead of the 0 - select @cmd = @cmd + 'case when [' + @column + '] = ''"null"'' then null else cast(' + @colstr + ' as ' + @type + ') end' + case when @nullable=0 then '), 0)' else '' end - select @cmd = @cmd + ' as ''' + @column + '''' -- add column name - select @crow = @crow + 1 - select @colid = colid, @column = [column], @type = [type], @length = [length], @precision = [precision], @scale = [scale], @nullable = [nullable] from #columns where colid=@crow - end - select @cmd = @cmd + ' FROM [ASB].[' + @table + '] OPTION (LABEL = ''CTAS : Load [' + @targetschema + '].[' + @table + ']'');' - select @i = 1 - while (@i < len(@cmd)) - begin - print substring(@cmd, @i, 1000) - select @i = @i + 1000 - end - print '' - exec(@cmd) - - -- Cleanup external objects - select @cmd = 'DROP EXTERNAL TABLE [ASB].[' + @table + ']' - print @cmd - exec(@cmd) - print 'DROP EXTERNAL DATA SOURCE AzureStorage' - DROP EXTERNAL DATA SOURCE AzureStorage - - -- Output row count and elapsed load time for the current table - select @cmd = 'select COUNT_BIG(*) as ''Rows in [' + @targetschema + '].[' + @table + ']'', ' + cast(datediff(s, @start, getdate())/60.0 as varchar(40)) + ' as ''Minutes to Load'' from [' + @targetschema + '].[' + @table + ']' - exec(@cmd) - - -- Increment to the next table - select @trow = @trow + 1 - select @objectid=objectid, @table=[table] from #tables where rowid=@trow - end -drop table #tables -drop table #columns diff --git a/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V3-ContainerSubfolders.sql b/Azure DW Load Scripts/Azure SQL DW Load Script Files/GenerateLoadScript-V3-ContainerSubfolders.sql deleted file mode 100644 index 6d0aab0b67f6d941a4aeaef34c6c8b27997c6cb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22994 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 A>Hq)$ diff --git a/Azure DW Load Scripts/Azure SQL DW Load Script Files/README.md b/Azure DW Load Scripts/Azure SQL DW Load Script Files/README.md deleted file mode 100644 index 371950a..0000000 --- a/Azure DW Load Scripts/Azure SQL DW Load Script Files/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# /***This Artifact belongs to the Data SQL Ninja Engineering Team***/ -# Auto Generate Azure SQL DW Load – TSQL Scripts - -Script Author: Mitch van Huuksloot, Solution Architect, Data SQL Ninja Engineering Team - -These scripts were developed to help with a large Azure SQL DW POC with one of the DMJ customers. Some of the assumptions made in the scripts are very specific to the scenario encountered at the customer. Feel free to adapt these scripts to your data loading scenario. - -Each of the scripts creates the appropriate objects to allow an optimal performance DW load from text files in blob storage into Azure SQL DW using Polybase. You can easily change the external data source to use Azure Data Lake as a source as well. The optimal nature of the load will depend on the number of files provided. Our customer had many gzip’d files that distributed well among several DW nodes (few larger gzip’d files would not have done as well). - -From a workflow perspective, we used SSMA for Oracle to generate the DW schema and then manually tweaked the data types in the script (the customer used the “number” data type without scale or precision indiscriminately). The SSMA default conversion of number to float(53) needed to be adjusted (given you are converting from precise to approximate). Part of the manual schema editing process was also deciding on distribution hash keys, which was an initial guess, since we didn’t have a list of typical queries. If we had no idea what to hash on, we left the tables round robin. For dimension tables, this would also be an appropriate time to make them replicated tables. We did not have row counts or sizes at that point, so we couldn’t make that determination (the guidance is a maximum size of 2 GB). - -Before running the schema script on the DW, we put all the tables into “source” schemas (SRC_XXX). The “source” schema is the template that the script uses to create the final tables in the target schema (including column types and distribution – note that no other indexes are created, beyond the default CCI index). Once a table is processed, just remove it from the source schema. We did not add this step to the script just in case there were errors that didn’t stop the script, but the drop could be easily added. - -In the POC, we had 72 tables split across 4 schemas, so we could load each schema separately with the script (note; to load multiple schemas in parallel with this script would require you to give the AzureStorage object a unique name for each copy of the script). - -During the POC, we had two locations where the customer put the text files to be loaded in Azure Blob Storage. Initially, they put the files in their own container under the same storage account. Many of the tables in their schema had underscore characters in the name, but the container names in blob storage had the table names with dashes instead of underscores (so the script has a replace to change this automatically). Later during the POC, the customer started moving newly extracted tables to a single container with a subfolder naming scheme (note; in blob store there aren’t actually subfolders, just a naming trick). There are therefore two different script versions, one for each case. In the first case we need to create a separate external data source for each container (we couldn’t get the root container syntax to work), while in the second case we can use the same external data source for every table and specify the subfolder in the external table creation command. - -The V1 script generates a set of “classic” load statements, where the external table definition has the appropriate types expected in each column. The CTAS statement then is just a simple “create table … select *…”. Also included is a single table CTAS load script that documents every step required to load one or more text files into a table in Azure SQL DW. - -During the POC, we started with the V1 script, but quickly determined that the script failed to load many of the customer tables for a variety of reasons, including; every column even numeric ones were quoted (which Polybase might have handled, except null values were specified as “null”), timestamps had too much precision for Polybase, embedded escaped quotes (\”) were not handled by Polybase, embedded new line characters caused Polybase to error etc. - -A strategy was developed to address some of the loading issues, which in some cases required the files to be re-extracted from the source system (hence the change during the POC of where files were stored). The customer originally had selected an ASCII 01 (SOH) character as the record separator. This seemed like a good choice, since, being an infrequently used control character, it should not appear in any of the text fields. The hope was that Polybase would not have an issue with it, and there wasn’t once we specified the value in the script in hex. - -Given the relatively exotic column separator, there really wasn’t a need for quotes around strings, but they were already in the generated files. We ended up having to remove the quote specification from the external file format definition, because the embedded quotes in columns were causing Polybase errors. In the process we switched to reading everything from the text files as character columns (or Unicode, if required) to reduce the number of Polybase issues we were seeing. Note that since we are reading everything into character columns and there may be embedded quotes in the strings, the character column lengths used are arbitrarily longer than the actual source columns length (we settled on adding 20 characters to character columns’ length). - -Instead of staging the raw file in a temp table, we came up with a strategy to cast the columns in the CTAS statement, to the appropriate data types (later we discovered the trick to add nullability). The complexity of the CTAS statement grew over time to handle many issues that we ran into. For some of the tables, the statements were longer than a print command could handle (so it is printed in multiple lines, with no concept of an appropriate line break location). - -One issue that was very problematic was newlines embedded in column text. We had the customer regenerate the files using an ascii 31 (RS) for an ascii 10 (LF) and an ascii 30 (US) for an ascii 13 (CR) and we added code to handle the replacement. They initially missed some columns with both CR and LF as newlines, but eventually they got them all. One table had a SOH character that showed up in one of the columns, which was very problematic to hunt down – the error was a string truncation but in column 85, but the problem column was actually 32. We had the customer regenerate the files for this table with a different record separator of an ascii 28 (FS) – this was a temporary script change that was not shared in this package but would be easy to replicate. - -If the script fails, you will need to manually remove the external table definition created (drop external table…). We could remove these tables automatically in the script but have no idea if there are multiple scripts running in parallel. - - - diff --git a/Azure DW Load Scripts/MICROSOFT LICENSE TERMS.docx b/Azure DW Load Scripts/MICROSOFT LICENSE TERMS.docx deleted file mode 100644 index 5bf1303bb93c81a1578052ba356bbee4dc6e2f86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20569 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 U`2Sq{K>@k}tO3bN{rv0y0h$vqApigX diff --git a/Azure DW Load Scripts/READ ME.docx b/Azure DW Load Scripts/READ ME.docx deleted file mode 100644 index 87d413fdc8e30c39dfe6a60f7cae111f718e1994..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23232 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 vTthZ1H2}L=h{hYbS*VphvRT