I managed to create a PowerShell script to download and load into a SQL Server database some files that have pivotted data: each day of the series is a column with the values of that day.
The problem is that it takes a long time to execute, about 15 seconds to load each file that has an average of 250 lines. I think the problem is when I try to get the values of the fields by its "index", because I didn't find a clever way of doing that.
Is there a better way of inserting this kind of CSV data that can change each day into the database using the PowerShell?
I don't know much of PowerShell scripting, but I managed to create the below scripts:
The files I downloaded from here:
https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_time_series
Script to process the files:
Clear-Host
$date = (Get-Date).Date.AddDays(-1).ToString('MM-dd-yyyy')
$path = 'C:\Dataset\'
$items = (Get-ChildItem -Path ($path + "time_series*.csv") | Select FullName) #| Select -First 1
$sql_instance_name = '.'
$db_name = 'COVID-19'
foreach ($item in $items)
{
$dt_start = Get-Date
$schema = "stg"
$table = (Split-Path -Path $item.FullName -Leaf).Split('.')[0]
Write-Host "File:"(Split-Path -Path $item.FullName -Leaf) -ForegroundColor Yellow
Write-Host "Schema: $schema" -ForegroundColor Yellow
Write-Host "Table: [$table]" -ForegroundColor Yellow
$header = (Get-Content $item.FullName | Select -First 1).replace(",", "|,|")
$i = 0; $new_header = #();
foreach ($column in $header.Replace('|', '').split(','))
{
$new_header += "Column_$i"
$i++
}
$drop_table = "if (object_id('stg.[$table]')) is not null drop table $schema.[$table];"
Invoke-Sqlcmd -Database $db_name -Query $drop_table -ServerInstance $sql_instance_name
$create_table = ("if (object_id('stg.[$table]')) is null
create table $schema.[$table] (" +
" id int identity constraint [pk_$table] primary key," +
" [" + $header + "] varchar(500),`n`tload_date datetime`n);").Replace('|,|', "] varchar(500), [")
Invoke-Sqlcmd -Database $db_name -Query $create_table -ServerInstance $sql_instance_name
$csv = Import-Csv -Path $item.FullName -Header $new_header | Select -Skip 1
$insert = $null
foreach ($row in $csv)
{
$query = "insert into stg.[" + (Split-Path -Path $item.FullName -Leaf).Split('.')[0] + "] values ("
foreach ($column in $new_header)
{
<# Perhaps this part slows down the process by the means of
getting the value for the column (I couldn't find a way to
simply reference the column by index like $csv.column[$i]
till the last one)
#>
$value = ($row | Select $column)
$query += "nullif('" + ($value | % { $_.$(( $value | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }).Replace("'", "''") + "',''),"
}
$query += " current_timestamp);"
$insert = $query
#Write-Host $row.Column_1
Invoke-Sqlcmd -Database $db_name -Query $insert -ServerInstance $sql_instance_name
}
Write-Host "Lines:"$csv.count -ForegroundColor Yellow
#Start-Sleep -Seconds 2
$dt_end = Get-Date
Write-Host "Elapsed time:"(New-TimeSpan -Start $dt_start -End $dt_end).TotalSeconds -ForegroundColor Red
Write-Host ("-" * 50)
}
Execution results:
File: time_series_covid19_confirmed_global.csv
Schema: stg
Table: [time_series_covid19_confirmed_global]
Lines: 264
Elapsed time: 14,3725288
--------------------------------------------------
File: time_series_covid19_deaths_global.csv
Schema: stg
Table: [time_series_covid19_deaths_global]
Lines: 264
Elapsed time: 14,1963788
--------------------------------------------------
File: time_series_covid19_recovered_global.csv
Schema: stg
Table: [time_series_covid19_recovered_global]
Lines: 250
Elapsed time: 13,5150064
--------------------------------------------------
If 2016+, you can download the JSON data.
If <2016, I believe there is an XML option as well
The download takes a couple of seconds, and the parsing of the JSON takes less than 4 seconds (depending on your hardware).
Example
exec master..xp_cmdshell 'powershell.exe Invoke-WebRequest "https://opendata.ecdc.europa.eu/covid19/casedistribution/json/" -OutFile "c:\working\covid.json"',no_output
Declare #json varchar(max);
Select #json = BulkColumn FROM OPENROWSET(BULK 'c:\working\covid.json', SINGLE_BLOB) x;
;with cte as (
Select [DataDate] = try_convert(date,DateRep,105)
,[CountryCd]= try_convert(varchar(50),countryterritoryCode)
,[Country] = try_convert(varchar(150),countriesAndTerritories)
,[Cases] = try_convert(int ,cases)
,[Deaths] = try_convert(int ,deaths)
,[Pop] = try_convert(int ,[popData2018])
,rtc = sum(try_convert(int ,cases)) over (partition by countryterritoryCode order by try_convert(date,DateRep,105))
,rtd = sum(try_convert(int ,deaths)) over (partition by countryterritoryCode order by try_convert(date,DateRep,105))
From (
Select Idx= B.[Key]
,C.*
From OpenJSON(#json ) A
Cross Apply OpenJson(A.value) B
Cross Apply OpenJson(B.value) C
) src
Pivot (max(value) for [Key] in ( [dateRep],[cases],[deaths],[countriesAndTerritories],[geoId],[countryterritoryCode],[popData2018] ) ) pvt
)
Select DataDate
,CountryCd
,Country
,Cases = format(Cases,'#,###')
,Deaths= format(Deaths,'#,###')
,Pop = format(Pop/1000000.0,'#,##0.0')+'MM'
,RTC = format(RTC,'#,###')
,RTD = format(RTD,'#,###')
,Mort = format((rtd*100.0) / nullif(rtc,0),'##0.00')+'%'
,PctPop= format((cases*100.0) / nullif(Pop,0),'##0.0000')+'%'
From cte
Where DataDate='2020-04-11'
Order By try_convert(money,RTC) desc
Returns
Related
I have a file with multiple expressions like "$REGX('CareMedic.2_0','CustomerInformation','Customer Information')". The file can be a xml file, text file or any other type. If the file contains 9 of those expressions, I'm trying to pull all nine and send the values to a database.
I've tried my code as below:
$input_path = ‘C:\Users\Administrator\Desktop\test2.xml’
$SQLServer = "WIN-17V7QT0IJVK"
$SQLDBName = "Test"
$uid ="WIN-17V7QT0IJVK\Administrator"
$pwd = "letmebackinplease"
$SqlQuery = "SELECT * from product_schema;"
$ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True;"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection $ConnectionString
$SqlConnection.open()
if($SqlConnection.state -eq "Open"){
Write-Host "Test connection successful"
}
$regex = '()\(.*?\)'
$output = select-string -Path $input_path -Pattern $regex -AllMatches | % { $.Matches } | % { $.Value } |
ForEach-Object {
($_ -split "\(|\)")[1]
}
foreach ($line in $output){
$line = $line -replace "\(",""
$line = $line -replace "\)",""
$line = $line -replace "\'",""
$col1,$col2,$col3 = $line -split ","
[PSCustomObject]#{
col1 = $col1
col2 = $col2
col3 = $col3
} | select col1,col2,col3
$insert_query = "INSERT INTO [$SQLDBName].[dbo].[product_schema]
([version]
,[field]
,[value])
VALUES
($col1, $col2, $col3);"
$execute_query = New-Object System.Data.SqlClient.SqlCommand
$execute_query.connection = $SQLConnection
$execute_query.commandtext = $insert_query
$execute_query.ExecuteNonQuery()
}
$SqlConnection.close()
If the file has two of the below:
('Medic.2_0','AgeInformation','Age Information')
('Medic.2_0','TransactionID','Transaction ID')
My actual output should be:
'Medic.2_0' stored in Version Column
'AgeInformation' stored in the Field Column
'Age Information' stored in the value column
'Medic.2_0' stored in Version Column
'TransactionID' stored in the Field Column
'Transaction ID' stored in the value column
I have to take each of the values and store it in a column in a temp table setup on MySQL server like below:
**Version** **Field** **Value**
Medic.2_0 AgeInformation Age Information
Medic.2_0 TransactionID Transaction ID
Error Encountered:
Exception calling "ExecuteNonQuery" with "0" argument(s): "Incorrect syntax near '.2'."
At C:\Users\Administrator\Desktop\test.ps1:47 char:10
+ $execute_query.ExecuteNonQuery()
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
Can someone please recommend how shall I change my code to solve this?
In answer to your original question before editing: Assuming your output looks like this and is saved in a variable named $output
('Medic.2_0','AgeInformation','Age Information')
('Medic.2_0','TransactionID','Transaction ID')
Try this:
foreach ($line in $output){
$line = $line -replace "\(",""
$line = $line -replace "\)",""
$line = $line -replace "\'",""
$col1,$col2,$col3 = $line -split ","
[PSCustomObject]#{
col1 = $col1
col2 = $col2
col3 = $col3
} | select col1,col2,col3 | export-csv d:\test.csv -append -NoTypeInformation
}
We are looping through the $output line by line removing the brackets and the single quotes, splitting the remaining text on the comma, then assigning each of the three entries into the relevant variables. Once they are in variables we can then easily create a PSObject and use it to select our requirements for our export-csv
Try to add this code:
$info=#() #for store your values
foreach($item in $output){
$z=$item.split(',') #for split to 3 strings
$info+=[PSCustomObject]#{ #create custom object which have named columns and store our values
Version = $z[0]
Field = $z[1]
Value = $z[2]
}
}
Write-Output $info #variable that store all columns
Then you must run foreach loop to each object in $info .
you can run it like this:
foreach($data in $info){
$data.Version #to access Version field
$data.Field #to access Field field
$data.Value #to access Value field
.......your SQL query......
}
I have scrubbed together some powershell to scan a directory list the contents and then insert to a MS SQL (2017) table without creating duplicates.
I am unable to to amend the MERGE to delete old/orphaned row in sql based on a compare of the current directory:
Add-Type -AssemblyName "System.Web"
function Get-FriendlySize {
param($Bytes)
$sizes='Bytes,KB,MB,GB,TB,PB,EB,ZB' -split ','
for($i=0; ($Bytes -ge 1kb) -and
($i -lt $sizes.Count); $i++) {$Bytes/=1kb}
$N=2; if($i -eq 0) {$N=0}
"{0:N$($N)} {1}" -f $Bytes, $sizes[$i]
}
#Declare Servername
$sqlServer='localhost'
#Invoke-sqlcmd Connection string parameters
$params = #{'server'='localhost';'Database'='kentico'}
#Fucntion to manipulate the data
Function writeDiskInfo
{
param ($FileName, $FileTitle, $FileDescription,$FileExtension,$FileMimeType,$FilePath,$FileSize,$FileImageWidth,$FileImageHeight,$FileGUID,$FileLibraryID,$FileSiteID,$FileCreatedByUserID,$FileCreatedWhen,$FileModifiedByUserID, $FileModifiedWhen,$FileCustomData,$FileDate)
# Data preparation for loading data into SQL table
$InsertResults = #"
Merge dbo.Media_File AS T
USING (SELECT FileName = '$FileName') AS S
ON S.FileName = T.FileName
WHEN NOT MATCHED BY TARGET THEN
INSERT (FileName,FileTitle,FileDescription,FileExtension,FileMimeType,FilePath,FileSize,FileImageWidth,FileImageHeight,FileGUID,FileLibraryID,FileSiteID,FileCreatedByUserID,FileCreatedWhen,FileModifiedByUserID,FileModifiedWhen,FileCustomData,FileDate)
VALUES ('$FileName','$FileTitle','$FileDescription','$FileExtension','$FileMimeType','$FilePath','$FileSize','$FileImageWidth','$FileImageHeight', '$FileGUID','$FileLibraryID','$FileSiteID','$FileCreatedByUserID','$FileCreatedWhen','$FileModifiedByUserID', '$FileModifiedWhen','$FileCustomData',CAST('$FileDate' AS datetime))
**This is where I get stuck**
WHEN NOT MATCHED BY SOURCE AND
(SELECT FileName = '$FileName') = T.FileName THEN
DELETE;
"#
#call the invoke-sqlcmdlet to execute the quer'
Invoke-sqlcmd #params -Query $InsertResults
}
#Query WMI query to store the result in a varaible
$dp = (get-childitem -Path C:\inetpub\wwwroot\Kentico11\CMS\t\media\test\ -Recurse -file |Select-Object -property #{Label='FileName';Expression={$_.baseName}},#{Label='FileTitle';Expression={$_.baseName}},#{N='FileDescription';E={"bob"}},#{Label='FileExtension';Expression={$_.Extension }},#{N='FileMimeType';E={[System.Web.MimeMapping]::GetMimeMapping("C:\inetpub\wwwroot\Kentico11\CMS\Enert\media\test\Compliance Analysis 2018-13-04.pdf")}},#{Label='FilePath';Expression= {($_.fullname.remove( 0, 58).replace( '\' ,'/'))}},#{N='FileSize';E={'1234'}},#{N='FileImageWidth';E={(Null)}},#{N='FileImageHeight';E={(Null)}},#{N='FileGUID';E={[guid]::newguid()}},#{N='FileLibraryID';E={("15")}},#{N='FileSiteID';E={("3")}},#{N='FileCreatedByUserID';E={("53")}},#{Label='FileCreatedWhen';Expression={$_.creationtime}},#{N='FileModifiedByUserID';E={("53")}}, #{Label='FileModifiedWhen';Expression={$_.creationtime}},#{N='FileCustomData';E={(Null)}},#{Label='FileDate';Expression={($_.baseName.Substring($_.basename.Length -13, 13))}})
#Loop through array
foreach ($item in $dp)
{
#Call the function to transform the data and prepare the data for insertion
writeDiskInfo $item.FileName $item.FileTitle $item.FileDescription $item.FileExtension $item.FileMimeType $item.FilePath $item.FileSize $item.FileImageWidth $item.FileImageHeight $item.FileGUID $item.FileLibraryID $item.FileSiteID $item.FileCreatedByUserID $item.FileCreatedWhen $item.FileModifiedByUserID $item.FileModifiedWhen $item.FileCustomData $item.FileDate
}
Invoke-Sqlcmd #params -Query "SELECT * FROM Media_File" | format-table -AutoSize
I have the following powershell script which reads in a list of servers, and runs SQL command on these servers. This data is then exported to csv and to excel format
I would like to be able to add the targeted server name from my server list as the first column so columns would look like this (server name added to front)
Server Name | Name | CollectionSet ID | Collection Mode | Retention Period | Schedule
This is the current script I have:
Param
(
[string]$fServers = 'W:\Theo\Scripts\mdw_servers.csv'
)
$query = "SELECT a.name AS 'DC Name',
collection_set_id AS 'Collection_set ID',
CASE collection_mode
WHEN 1 THEN 'non-cached'
WHEN 0 THEN 'cached'
END AS 'Collection Type' ,
days_until_expiration AS 'Retention Period' ,
b.name AS 'Schedule Name'
FROM msdb.dbo.syscollector_collection_sets a ,
msdb.dbo.sysschedules b
WHERE a.schedule_uid = b.schedule_uid
AND is_running = 1;"
$csvFilePath = "W:\Theo\Scripts\queryresults.csv"
$excelFilePath = "W:\Theo\Scripts\queryresults.xls"
# Run Query against multiple servers, combine results
$allServers = Get-Content -Path $fServers
foreach ($Server in $allServers) {
write-host "Executing query against server: " $Server
$results += Invoke-Sqlcmd -Query $query -ServerInstance $Server;
}
# Output to CSV
write-host "Saving Query Results in CSV format..."
$results | export-csv $csvFilePath -NoTypeInformation
# Convert CSV file to Excel
write-host "Converting CSV output to Excel..."
$excel = New-Object -ComObject excel.application
$excel.visible = $False
$excel.displayalerts=$False
$workbook = $excel.Workbooks.Open($csvFilePath)
$workSheet = $workbook.worksheets.Item(1)
$resize = $workSheet.UsedRange
$resize.EntireColumn.AutoFit() | Out-Null
$xlExcel8 = 56
$workbook.SaveAs($excelFilePath,$xlExcel8)
$workbook.Close()
$excel.quit()
$excel = $null
write-host "Results are saved in Excel file: " $excelFilePath
Any input is appreciated!
have you tried
SELECT ##SERVERNAME AS 'Server Name'
https://msdn.microsoft.com/en-us/library/ms187944.aspx
Working on another script for work and I'm attempting to read from a CSV containing only one column of data. And then for each item to find the corresponding ID when querying the SQL database. Then to put the result(ID1, CSVID1) in to an excel file(I have this part working fine).
Now I have run in to an issue as to how to populate the dataset within a foreach loop.
$excelAssets = Import-Csv .\test.csv -Header assetId | Foreach-Object {
$assetId = $_.assetId
# SQL Query Variables
$query = "SELECT AssetId AS AssetID, BrandId AS BrandID FROM [AssetLibrary_BrandAsset] WHERE AssetId = $assetId"
$connection = New-SqlConnection -Server $dataSource -Database $dataBase
#Execute the SQL commands and place the results in dataset
if ($connection.State -eq 'Open')
{
$swLap = Start-Elapsed $sw "Executing SQL Query"
Write-Verbose "$query";
$dataSet += Invoke-SQLQuery -connection $connection -query $query -ExecutionTimeout '0'
$i++
$connection.Close();
End-Elapsed $sw $swLap
} ELSE {
Write-Error "$($(Format-Elapsed $swLap)) SQL Connection Not Open - Exiting...";
exit;
}
}
Now $dataSet += doesn't work and I have googled numerous times to try and find the answer to this problem. Any help is appreciated.
Using the $dataSet
$dataTable = new-object "System.Data.DataTable" "Results"
$dataTable = $dataSet.Tables[0]
$rowDT = $dataTable.Rows.Count;
$colDT = $dataTable.Columns.Count;
Write-Host -NoNewLine "$(Format-Elapsed $sw.Elapsed) Rows: ";
Write-Host -NoNewLine "$($rowDT+1)" -ForegroundColor "Green";
Write-Host -NoNewLine " Columns: "
Write-Host -NoNewLine "$($colDT+1)" -ForegroundColor "Green";
Write-Host -NoNewLine " Cells: "
Write-Host "$( ($colDT+1)*($rowDT+1) )" -ForegroundColor "Green";
#Create a 2D Array of the DataTable
# http://stackoverflow.com/questions/13184191/fastest-way-to-drop-a-dataset-into-a-worksheet
$tableArray = New-Object 'object[,]' $rowDT, $colDT;
$swLap = Start-Elapsed $sw "DataTable transformation"
# i = row and j = column
for ($i=0;$i -lt $rowDT; $i++)
{
#Write-Progress -Activity "Transforming DataTable" -status "Row $i" -percentComplete ($i / $rowDT*100)
for ($j=0;$j -lt $colDT; $j++)
{
$tableArray[$i,$j] = $dataTable.Rows[$i].Item($j).ToString();
}
}
End-Elapsed $sw $swLap
$rowOffset = 1; $colOffset = 1;# 1,1 = "A1"
# Write out the header column names
for ($j=0;$j -lt $colDT; $j++)
{
$ActiveWorksheet.cells.item($rowOffset, $j+1) = $dataTable.Columns[$j].ColumnName;
}
$headerRange = $ActiveWorksheet.Range($ActiveWorksheet.cells.item($rowOffset, $colOffset), $ActiveWorksheet.cells.item($rowOffset, $colDT+$colOffset-1));
$headerRange.Font.Bold = $false
$headerRange.Interior.Color = $headingColour
$headerRange.Font.Name = $headingFont
$headerRange.Font.Color = $headingFontColour
$rowOffset++;
# Extract the data to Excel
$tableRange = $ActiveWorksheet.Range($ActiveWorksheet.cells.item($rowOffset, $colOffset), $ActiveWorksheet.cells.item($rowDT+$rowOffset-1, $colDT+$colOffset-1));
$tableRange.Cells.Value2 = $tableArray;
# Resize the columns in Excel
$swLap = Start-Elapsed $sw "Resize Excel Worksheet"
$wholeRange = $ActiveWorksheet.UsedRange
$wholeRange.EntireColumn.AutoFit() | Out-Null
End-Elapsed $sw $swLap
# Save Excel workbook
$ActiveWorkbook.SaveAs("$OutputFile")
$ActiveWorkbook.Close()
After assigning to $dataSet the first time, it's type is probably not array, meaning that the += operator doesn't behave exactly as you expect.
You can either initialize $dataSet as an empty array before you start assigning to it:
Import-Csv .\test.csv -Header assetId | Foreach-Object -Begin {$dataSet = #()} -Process {
# rest of script in here
} -End {return $dataSet}
or you can cast it during assigning:
[array]$dataSet += Invoke-SQLQuery -connection $connection -query $query -ExecutionTimeout '0'
finally, an alternative solution would be to ensure that the output from Invoke-SQLQuery is treated as an array before you assign it to $dataSet:
$dataSet += #(Invoke-SQLQuery -connection $connection -query $query -ExecutionTimeout '0')
Whatever suits your style of coding.
I am using the Scripter class to give me a script for the data out of an existing database. I want to script a dataset that can be inserted into a production database. We are doing this to test if an installation of our Software is correct.
Unfortunately the dataset has to be removed later without any entries left behind so that it does not interfere with the data of our customers. So what I need are INSERT and DELTE statements. These are maintained manually at the moment which is too much of a burden.
Very well so I just went and executed the Scripter twice (once for INSERT, once for DELETE)
Problem is that when setting ScriptDrops to true then the output is in the form
DELETE FROM [dbo].[TableName]
What I would like is something of the form:
DELETE FROM [dbo].[TableName] WHERE ID = 'GUID'
Technically this would be possible since there are Primary Keys on all the tables.
The Scripter class must also in some form know of that things since it also gets the order of the DELETE-statements (dependencies) correct via foreign keys.
Any help on this would be appreciated.
Following are the 2 PowerShell-scripts I am using to export the data:
ScriptRepositoryData.ps1
$scriptPath = $MyInvocation.MyCommand.Path
$scriptDirectory = Split-Path $scriptPath -Parent
. $scriptDirectory\DatabaseScripting.ps1
$filepath='c:\data.sql'
$database='ECMS_Repository'
$tablesToExclude = #(
"SomeUnwantedTable"
)
$tablesListFromDatabase = GetTableList $database
$tablesArray = #()
$tablesListFromDatabase |% {
if (-not $tablesToExclude.Contains($_.Name.ToString()))
{
$tablesArray += $_.Name
}
}
ScriptInsert $database $tablesArray $filepath
DatabaseScripting.ps1
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMOExtended") | out-null
Function GetTableList ($database)
{
Invoke-SqlCmd -Database $database -query "SELECT * FROM sys.tables"
}
Function ScriptInsert ($database, $tables, $destination)
{
try {
$serverMO = new-object ("Microsoft.SqlServer.Management.Smo.Server") "localhost"
if ($serverMO.Version -eq $null) {Throw "Can't find the instance localhost"}
$urnsToScript = New-Object Microsoft.SqlServer.Management.Smo.UrnCollection
$databaseMO = $serverMO.Databases.Item("ECMS_Repository")
if ($databaseMO.Name -ne $database) {Throw "Can't find the database $database"}
$tables |% {
$tableListMO = $databaseMO.Tables.Item($_, "dbo")
$tableListMO |% {
$urnsToScript.Add($_.Urn)
}
}
$scripter = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') $serverMO
$scripter.Options.ScriptSchema = $False;
$scripter.Options.ScriptData = $true;
$scripter.Options.ScriptDrops = $true;
$scripter.Options.ScriptAlter = $true;
$scripter.Options.NoCommandTerminator = $true;
$scripter.Options.Filename = $destination;
$scripter.Options.ToFileOnly = $true
$scripter.Options.Encoding = [System.Text.Encoding]::UTF8
$scripter.EnumScript($urnsToScript)
Write-Host -ForegroundColor Green "Done"
}
catch {
Write-Host
Write-Host -ForegroundColor Red "Error occured"
Write-Host
Write-Host $_.Exception.ToString()
Write-Host
}
}
Unfortunately I did not find a way to do this using the Sql Management Objects.
Anyhow I now use the output of the Scripter and select the IDs of each table. I then use the IDs to change every line that looks like
DELETE FROM [dbo].[tableName]
to this:
DELETE FROM [dbo].[tableName] WHERE ID IN ('guid1', 'guid2')
Here is how I did it:
$content = Get-Content $destination
Clear-Content $destination
$content |% {
$line = $_
$table = $line.Replace("DELETE FROM [dbo].[","").Replace("]","")
$query = "SELECT ID, ClassID FROM" + $_
$idsAsQueryResult = Invoke-SqlCmd -Database $database -query $query
$ids = $idsAsQueryResult | Select-Object -Expand ID
if ($ids -ne $null) {
$joinedIDs = [string]::Join("','",$ids)
$newLine = $line + " WHERE ID IN ('" + $joinedIDs + "')"
Add-Content $destination $newLine
}
}
Where $destination is the script that has been generated with the Scripter class and $database is a string containing the database name.
I had to select a second column (ClassID which is there on all tables due to our OR mapper re-store) because of some weird error in Select-Object which I do not fully understand.
This of course only works because all tables have primary keys and all primary keys are named ID and are not combined primary keys or something.
You could of course achieve the same thing for other more complicated database schemas by extracting primary key information via SQL management objects.