Advertisement
Guest User

Merge-DataTableToSQL.ps1

a guest
Sep 28th, 2016
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Merge the datatable into SQL
  2. function Merge-DataTableToSQL {
  3.     <#
  4.         .EXAMPLE
  5.         Merge-DataTableToSQL -SQLServer fitchmsql01 -SQLDB dev -Target dbo.adusers -Source $DataTable
  6.         .PARAMETER Source
  7.         A DataTable that will be merged witht eh target tabled.
  8.         .PARAMETER SQLServer
  9.         Named instances SERVERNAME\INSTANCENAME | If it's a default instance only use server name, do not add \MSSQLSERVER.
  10.         .PARAMETER SQLDB
  11.         Name of the database where the target table is.
  12.         .PARAMETER Target
  13.         The Table in which you're targeting
  14.         .PARAMETER Filter
  15.         Default="*" Used in selecting the columns from the target.
  16.         .PARAMETER Security
  17.         Default="SSPI" Used in connection string to SQL DB. User account running script should have permission to create and drop tables.
  18.         .PARAMETER Timeout
  19.         Default="60" Used in connection string.
  20.     #>
  21.         [CmdletBinding()]
  22.     param(
  23.         [Parameter(Mandatory=$true)][string]$ServerInstance,
  24.         [Parameter(Mandatory=$true)][string]$Database,
  25.         [Parameter(Mandatory=$true)][string]$Target,
  26.         [Parameter(Mandatory=$true)][System.Data.DataTable]$Source,
  27.         [String]$Filter="*",
  28.         [parameter()][System.Management.Automation.PSCredential]$Cred
  29.     )
  30.  
  31.     Begin {
  32.         #Create connection object to SQL instance
  33.         $SQLConnection = New-Object System.Data.SqlClient.SqlConnection
  34.         $SQLConnection.ConnectionString = "Server = $ServerInstance;Database=$Database;User ID=$($cred.UserName);Password=$($cred.GetNetworkCredential().password);"
  35.         $SQLConnection.Open()
  36.     }
  37.     Process{
  38.         if ($SQLConnection.State -ne [Data.ConnectionState]::Open){"Connection to SQL DB not open"}
  39.         else{
  40.             #Get columns for table in SQL and compare to column in source DataTable
  41.             $SQLCommand = New-Object System.Data.SqlClient.SqlCommand
  42.             $SQLCommand.Connection = $SQLConnection
  43.             $SQLCommand.CommandText = "SELECT $($Filter) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_Name = '$(($Target.Split(".") | Select -Index 1))'"
  44.             $SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
  45.             $SQLAdapter.SelectCommand = $SQLCommand
  46.             $SQLColumns = New-Object System.Data.DataTable
  47.             $SQLAdapter.Fill($SQLColumns) | Out-Null
  48.             $Columns = $SQLColumns.COLUMN_NAME
  49.             if ($Compare = ((Compare-Object $SQLColumns.COLUMN_NAME $Source.Columns.ColumnName -PassThru) -join ", ")){
  50.             "DataTable and SQL table contain different columns: $Compare"
  51.             }
  52.             else{
  53.  
  54.                 #What is the primary key of the target table
  55.                 $PrimaryKey = New-Object System.Data.DataTable
  56.                 $SQLCommand.CommandText = "SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_Name = '$($Target.Split(".") | Select -Index 1)' AND CONSTRAINT_NAME LIKE 'PK_%'"
  57.                 $SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
  58.                 $SQLAdapter.SelectCommand = $SQLCommand
  59.                 $SQLAdapter.Fill($PrimaryKey) | Out-Null
  60.                 $PrimaryKey = $PrimaryKey | Where-Object {$_.CONSTRAINT_NAME -like 'PK_*'} | Select -ExpandProperty COLUMN_NAME -First 1
  61.                 if($PrimaryKey -eq $null){"SQL Table does not have primary key"
  62.                 }
  63.                 else{
  64.                     #Create temporary table for bulk insert
  65.                     $CreateColumns = ($CreateColumns = foreach($Column in ($Columns | Where-Object {$_ -ne $PrimaryKey})){"["+$Column+"] [nvarchar] (max) NULL"}) -join ","
  66.                     $SQLQuery = "CREATE TABLE $($Target)_TEMP([$($PrimaryKey)] [nvarchar](255) NOT NULL PRIMARY KEY, $CreateColumns)"
  67.                     $SQLCommand.CommandText = $SQLQuery
  68.                     $Results = $SQLCommand.ExecuteNonQuery()
  69.                     if ($Results -ne -1){"Unable to create temp table $($Target)_TEMP"}
  70.                     else{
  71.  
  72.                         #Bulk insert source DataTable into temporary SQL table
  73.                         $SQLBulkCopy = New-Object ("System.Data.SqlClient.SqlBulkCopy") $SQLConnection
  74.                         $SQLBulkCopy.DestinationTableName = "$($Target)_TEMP"
  75.                         $SQLBulkCopy.BatchSize = 5000
  76.                         $SQLBulkCopy.BulkCopyTimeout = 0
  77.                         foreach ($Column in $Columns){[void]$SQLBulkCopy.ColumnMappings.Add($Column, $Column)}
  78.                         $SQLBulkCopy.WriteToServer($Source)
  79.  
  80.                         #Build and execute SQL merge command
  81.                         #$Updates = (($Updates = foreach ($Column in $Columns -ne $PrimaryKey)
  82.                         #{
  83.                         #    "Target.[$($Column)]"+" = "+("Source.[$($Column)]")
  84.                         #}) -join ",")
  85.                         $InsertColumns = ($InsertColumns = foreach ($Column in $Columns){"[$Column]"}) -join ","
  86.                         $InsertValues = ($InsertValues = foreach ($Column in $Columns){"Source.[$Column]"}) -join ","
  87. #Do not align this text!
  88. $SQLQuery = @"
  89. MERGE INTO $($Target) AS Target
  90. USING $($Target)_TEMP AS Source
  91. ON Target.[$($PrimaryKey)] = Source.[$($PrimaryKey)]
  92. WHEN NOT MATCHED THEN
  93.    INSERT ($InsertColumns) VALUES ($InsertValues)
  94. WHEN NOT MATCHED BY Source THEN
  95.    DELETE;
  96. "@
  97.                         $SQLCommand.CommandText = $SQLQuery
  98.                         try{
  99.                             $Results = $SQLCommand.ExecuteNonQuery()
  100.                         }
  101.                         catch{
  102.                             Write-Host "Exception with SQL Command: MERGE INTO $Target USING $($Target)_TEMP | Can be caused by incorrect Data Types"
  103.                         }
  104.                         "$Results rows affected"
  105.                         #Drop temporary table
  106.                         $SQLCommand.CommandText = "DROP TABLE $($Target)_TEMP"
  107.                         $Results = $SQLCommand.ExecuteNonQuery()
  108.                         if($Results -ne -1){
  109.                             "Unable to DROP TABLE $($Target)_TEMP"
  110.                             }
  111.                         #End of create temporary table
  112.                         }
  113.                     #End of require primary key
  114.                     }
  115.                 #End of compare DataTable and SQL Table columns
  116.                 }
  117.             }
  118.     }
  119.     end{
  120.         if ($SQLConnection.State -eq [Data.ConnectionState]::Open){
  121.             $SQLConnection.Close()
  122.         }
  123.     }
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement