Public/Write-InsertOrUpdate.ps1
function Write-InsertOrUpdate { <# .SYNOPSIS Write INSERT OR UPDATE SQL query .DESCRIPTION Check if record key exists and insert or update data in a table .PARAMETER Table The table parameter corresponds to the name of the table in which to insert or update records. Remark: It is recommended to use the fully qualified table name. .PARAMETER Fields The fields parameter corresponds to the list of table columns and their corresponding values. .PARAMETER PrimaryKey The primary key parameter corresponds to the column constituting the unique key identifier of the record in the specified table. .PARAMETER Vendor The optional vendor parameter corresponds to the database vendor used to define the syntax to use for the SQL statement. The available values are: - Oracle: Oracle database - SQLServer: Microsoft SQL Server database The default value is SQLServer because it is fully integrated with PowerShell and for legacy support purposes. .PARAMETER Identity The identity switch allows identity fields to be modifed. .EXAMPLE $Fields = [Ordered]@{ "column1" = "value1" "column2" = "value2" "column3" = "value3" "column4" = "value4" } Write-InsertOrUpdate -Table "Test" -Fields $Fields -PrimaryKey @("column1", "column2") In this example, the function will check the table "Test" to see if the columns "column1" and "column2" contains respectively the values "values1" and "values2". If a record is found, the the returned query will update the values of the columns "columns3" and "columns4". In no corresponding record is found, the returned query will insert a new record with the specified values. .NOTES File name: Write-InsertOrUpdate.ps1 Author: Florian Carrier Creation date: 2019-10-15 Last modified: 2020-02-26 #> [CmdletBinding ( SupportsShouldProcess = $true )] Param ( [Parameter ( Position = 1, Mandatory = $true, HelpMessage = "Table name" )] [ValidateNotNullOrEmpty ()] [String] $Table, [Parameter ( Position = 2, Mandatory = $true, HelpMessage = "List of fields" )] [ValidateNotNullOrEmpty ()] [System.Collections.Specialized.OrderedDictionary] $Fields, [Parameter ( Position = 3, Mandatory = $true, HelpMessage = "Primary key to use for the existence check" )] [ValidateNotNullOrEmpty ()] [Alias ("PK")] [String[]] $PrimaryKey, [Parameter ( Position = 4, Mandatory = $false, HelpMessage = "Database vendor (syntax)" )] [ValidateSet ( "Oracle", "SQLServer" )] [Alias ("Syntax")] [String] $Vendor = "SQLServer", [Parameter ( HelpMessage = "Switch to enable working with identities" )] [Switch] $Identity ) Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # Check that values are provided for the primary key foreach ($Key in $PrimaryKey) { if (Find-Key -Hashtable $Fields -Key $Key) { if ($Fields.$Key -eq $null) { Write-Log -Type "ERROR" -Object "Missing value for primary key $Key" -ExitCode 1 } } else { Write-Log -Type "ERROR" -Object "The primary key $Key is not in the list of fields provided" -ExitCode 1 } } } Process { switch ($Vendor) { "Oracle" { # Define existence check foreach($Key in $PrimaryKey) { if ($PrimaryKeyCheck -eq $null) { $PrimaryKeyCheck = "$Key = $($Fields.$Key)" } else { $PrimaryKeyCheck += " AND $Key = $($Fields.$Key)" } } $Check = [System.String]::Concat("MERGE INTO $Table USING dual ON (", $PrimaryKeyCheck, ")") # Loop through fields foreach ($Field in $Fields.GetEnumerator()) { # Select update values if ($Field.Key -NotIn $PrimaryKey) { if ($UpdateValues -eq $null) { $UpdateValues = "$($Field.Key) = $($Field.Value)" } else { $UpdateValues += ", $($Field.Key) = $($Field.Value)" } } # Set insert fields if ($InsertFields -eq $null) { $InsertFields = "$($Field.Key)" } else { $InsertFields += ", $($Field.Key)" } # Set insert values if ($InsertValues -eq $null) { $InsertValues = "$($Field.Value)" } else { $InsertValues += ", $($Field.Value)" } } # Construct update query $Update = [System.String]::Concat("WHEN MATCHED THEN UPDATE SET ", $UpdateValues) # Construct insert query $Insert = [System.String]::Concat("WHEN NOT MATCHED THEN INSERT (", $InsertFields, ") VALUES (", $InsertValues, ")") # Construct whole SQL query $Query = [System.String]::Concat($Check, "`n", $Update, "`n", $Insert) # TODO } "SQLServer" { # Define existence check foreach($Key in $PrimaryKey) { if ($PrimaryKeyCheck -eq $null) { $PrimaryKeyCheck = " WHERE $Key = $($Fields.$Key)" } else { $PrimaryKeyCheck += " AND $Key = $($Fields.$Key)" } } $Check = [System.String]::Concat("IF EXISTS (SELECT COUNT(1) FROM " , $Table, $PrimaryKeyCheck, ")") # Loop through fields foreach ($Field in $Fields.GetEnumerator()) { # Select update values if ($Field.Key -NotIn $PrimaryKey) { if ($UpdateValues -eq $null) { $UpdateValues = "$($Field.Key) = $($Field.Value)" } else { $UpdateValues += ", $($Field.Key) = $($Field.Value)" } } # Set insert fields if ($InsertFields -eq $null) { $InsertFields = "$($Field.Key)" } else { $InsertFields += ", $($Field.Key)" } # Set insert values if ($InsertValues -eq $null) { $InsertValues = "$($Field.Value)" } else { $InsertValues += ", $($Field.Value)" } } # Construct update query $Update = [System.String]::Concat("UPDATE ", $Table, " SET ", $UpdateValues, $PrimaryKeyCheck) # Construct insert query $Insert = [System.String]::Concat("INSERT INTO ", $Table, " (", $InsertFields, ") VALUES (", $InsertValues, ")") # Construct whole SQL query $Query = [System.String]::Concat($Check, "`nBEGIN`n`t", $Update, "`nEND`nELSE`nBEGIN`n`t", $Insert, "`nEND") # Check identity flag if ($PSBoundParameters.ContainsKey["Identity"] -eq $true) { # Manage IDENTITY_INSERT $EnableIdentityInsert = "SET IDENTITY_INSERT $Table ON" $DisableIdentityInsert = "SET IDENTITY_INSERT $Table OFF" $Query = [System.String]::Concat($EnableIdentityInsert, "`n", $Query, "`n", $DisableIdentityInsert) } } default { Write-Log -Type "ERROR" -Object "Unsupported database vendor $Vendor" return $null } } # Return query Write-Log -Type "DEBUG" -Object $Query return $Query } } |