Welcome › Forums › General PowerShell Q&A › Add switch statements to script
- This topic has 5 replies, 3 voices, and was last updated 1 week, 5 days ago by
Participant.
-
AuthorPosts
-
-
December 16, 2020 at 8:48 am #280191PowerShell123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187param([string]$Path,[string]$ConnectionString,[string]$Table,[string]$Delimiter = ',',[int]$BatchSize = 75000,[switch]$StopOnError,[switch]$TruncateLongValues,[switch]$NoHeaders,[switch]$EmptyValueIsNull)$ErrorActionPreference = 'Stop'$columnLengthSql = @"selectc.[max_length]from sys.columns cinner join sys.objects oon c.object_id = o.object_id and o.type = 'U'where o.Name = N'{0}'order by c.column_id"@try{# Connect to SQL Server$conn = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)$conn.Open()# Read the column widths, which we will use to check string (char type) columns$columnWidths = Invoke-Command -NoNewScope -ScriptBlock {try{$cmd = $conn.CreateCommand()$cmd.CommandText = [string]::Format($columnLengthSql, $Table)$cmd.CommandType = 'Text'$rdr = $cmd.ExecuteReader()while ($rdr.Read()){# Emit with into array[int]$rdr[0]}}finally{($rdr, $cmd) |ForEach-Object {$_.Dispose()}}}# Number of columns in the target table$columnCount = $columnWidths.Count# Set up BCP stuff$bcpOption = ([System.Data.SqlClient.SqlBulkCopyOptions]::TableLock -bor [System.Data.SqlClient.SqlBulkCopyOptions]::UseInternalTransaction)$bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($conn, $bcpOption, $null)$bulkcopy.DestinationTableName = $Table$bulkcopy.bulkcopyTimeout = 0$bulkcopy.batchsize = $BatchSize$datatable = New-Object System.Data.DataTable# Get the column data for the given table# Sneakily selecting 1 row from the table puts the schema into the datatabletry{$sql = 'select top 1 * from [' + $Table + ']'$dad = New-Object System.Data.SqlClient.SqlDataAdapter($sql, $conn)[void]$dad.Fill($datatable)}finally{$dad.Dispose()}# If we read a row, clear it.$datatable.Clear()# Init row counter$i = 0# Headers, or not?$headerArgument = @{}if ($NoHeaders){# If user specifies -NoHeaders, generate dummy headers - as many as there are columns$headings = Invoke-Command -NoNewScope -ScriptBlock {for ($i = 0; $i -lt $columnWidths.Length; $i++){"Dummy$($i)"}}$headerArgument = @{ Header = $headings }}# Let Import-Csv deal with delimiter nonsense!Import-Csv -Path $Path -Delimiter $Delimiter @headerArgument |ForEach-Object {try{# Validate imput column count# Import-Csv *ignores* extra columns in the input, so we will never know about them!# Empty columns, e.g. blah,,blah are rendered as empty strings.# If there are too few values, the remaining columns are rendered as $null (.NET null, not database null)$populatedColumnCount = ($_.PSObject.Properties.Value | Where-Object { $_ -ne $null } | Measure-Object).Countif ($populatedColumnCount -ne $columnCount){throw "Incorrect number of columns in input. Got $($populatedColumnCount), expected $columnCount"}if ($TruncateLongValues -or $EmptyValueIsNull){# Check columns - this will slow things down somewhatfor ($col = 0; $col -lt $datatable.Columns.Count; ++$col){$inputValue = $_.PSObject.Properties.Value[$col].ToString()if ($EmptyValueIsNull -and [string]::IsNullOrEmpty($inputValue)){$_."$($_.PSObject.Properties.Name[$col])" = [System.DBNull]::Value}elseif ($datatable.Columns[$col].DataType.FullName -eq 'System.String' -and $inputValue.Length -gt $columnWidths[$col]){Write-Warning "Row $($i + 1), Col $($col + 1): Value truncated"$_."$($_.PSObject.Properties.Name[$col])" = $inputValue.Substring(0, $columnWidths[$col])}}}[void]$datatable.Rows.Add($_.PSObject.Properties.Value)}catch{# Column datatype mismatchif ($StopOnError){# Stop immediatelythrow}# Warn the user a row didn't go in and continueWrite-Warning "Row $($i + 1): $($_.Exception.Message)"}if ((++$i % $BatchSize) -eq 0){# Write batch$bulkcopy.WriteToServer($datatable)$datatable.Clear()}}if ($datatable.Rows.Count -gt 0){# Write remaining rows$bulkcopy.WriteToServer($datatable)$datatable.Clear()}}catch{# A good script will handle exceptions here,# e.g. failure to connect to SQL server, incorrect/un-castable datatype for column etc.# for now, just re-throwthrow}finally{# Clean up in finally block - ensures resources are released even in event of errors.($bulkcopy, $datatable, $conn) |Where-Object { $_ -ne $null } |ForEach-Object {$_.Dispose()}}
I want to add a few other switches to this script. truncate table and csvlinecnt and loadcnt. I would like to clear the
table before loading, and count the number of lines to load in csv and count records loaded.Maybe even put any output from script in an email for load tracing.
Thanks.
-
December 16, 2020 at 11:08 am #280263
Are you the author of this script ? let us know little more on what problem are you facing here.
-
December 16, 2020 at 11:19 am #280281
This was a script I asked for some help creating, as I had something similar, but it wasn’t doing the switch’s in the original design. I would like to add more functionality of record counts both of the csv and “what loaded to SQL”. Then I thought
adding a TruncateTable since I would always be loading a Staging table.Thanks.
-
January 4, 2021 at 1:07 pm #284086
Any help in adding a few new options to this script?
Thanks
-
January 4, 2021 at 2:24 pm #284101
Sounds like when you say “switch statements” you mean switch parameters. As your script is now, I don’t see any switch statements. See Get-Help about_switch
To add switch parameters, just put them in the param block and reference them in the script where appropriate. These will be simply True of False depending on if the caller included the switch, so you can use a simple if statement like you see in line 90 and 122 of your current posted script.
Recommend you refine your new requirements some more and try to implement the code as much as you can, then maybe someone can help you with logic/errors as needed. Right now what you are trying to accomplish seems a little vague to me.
-
January 8, 2021 at 11:06 am #284785
One of the requirements was to Truncate Table, the other where to verify records in csv match to what was loaded.
If not send alert of the records loaded didn’t match records received.
-
-
AuthorPosts
- You must be logged in to reply to this topic.