Replace Multiple Strings in a SQL File using PowerShell - powershell

I am able to replace a single string in a SQL file using PowerShell as follows:
$newPrefix = "foo'
$dbUserMappingScriptPath = "C:\MySQL_Template.sql"
$updatedDbUserMapingScriptPath = "C:\MySQL.sql"
(gc $dbUserMappingScriptPath).Replace('DBPrefix_',$newPrefix) | sc $updatedDbUserMapingScriptPath
This is great for single scenarios, but I need to replace multiple strings. I have tried the following, but it doesn't perform the replace operation beyond replacing the first string of 'DBPrefix_' with $newPrefix. It does not perform the replacements for 'MDFDatabasePath' and 'LDFDatabasePath'.
How do I replace multiple strings given the following snippet? Note that this is wrapped in a Foreach-Object for the $.MDFDatabasePath and $.LDFDatabasePath values.
$dbUserMappingScriptPath = "C:\MySQL_Template.sql"
$updatedDbUserMapingScriptPath = "C:\MySQL.sql"
(gc $dbUserMappingScriptPath).Replace('DBPrefix_',$newPrefix).Replace('MDFDatabasePath',$_.MDFDatabasePath).Replace('LDFDatabasePath',$_.LDFDatabasePath) | sc $updatedDbUserMapingScriptPath
Here is a snippet of my SQL:
USE [master]
GO
CREATE DATABASE [DBPrefix_mydb] ON
( FILENAME = N'MDFDatabasePath\DBPrefix_mydb.MDF' ),
( FILENAME = N'LDFDatabasePath\DBPrefix_mydb.ldf' )
FOR ATTACH
GO
UPDATE: I had a mismatch in my PowerShell script in that I was running the replace on the wrong SQL script. The code above with an extra .Replace works like a charm

Related

PowerShell 5.1 handling sql server nvarchar datatype

I am loading a DataTable with data from SQL Server as such:
$queryStr = "SELECT TOP 10 ID, QueryText FROM dbo.DatabaseName";
$dataRows = Invoke-DbaQuery -SqlInstance instance.name -Database databasename -Query $queryStr -As DataSet;
In SQL Server the QueryText is nvarchar(max). In PowerShell, this becomes a string datatype, equal to varchar I think. I think this because when I try to calculate the hash in PowerShell with Get-FileHash, and in SQL Server I calculate the hash on the nvarchar column with SELECT (CONVERT([varchar](70),hashbytes('SHA2_256', QueryText),(1))), the hashes do not match.
They DO match however, if I convert the nvarchar to a varchar(max) in SQL Server.
So the question is, in PowerShell how can I convert the string datatype to match the nvarchar datatype in SQL Server? Because as far as I know, PowerShell does not have a nvarchar datatype, just the generic string datatype.
Added this part after reading comments.
In the DataTable that I retrieve from SQL Server as per the above code I add an extra column to hold the hash that I calculate in PowerShell.
Add extra column to DataTable:
$HashColumn = [System.Data.DataColumn]::new('QueryHashString', [string]);
$dataRows.Tables[0].Columns.Add($HashColumn);
Now I do a foreach to fill this column I just added:
foreach($row in $dataRows.Tables[0]) {
$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write("$($row.QueryText)")
$writer.Flush()
$stringAsStream.Position = 0
$row.QueryHashString = (Get-FileHash -InputStream $stringAsStream | Select-Object -ExpandProperty Hash)
}
Your code uses StreamWriter that uses the default UTF-8 encoding, which matches what you get with hashing a VARCHAR -- if you stick to ASCII characters. To hash Unicode instead (and for variation, let's use SHA256 directly instead of going through Get-FileHash, and throw in an emoji so we have to deal with surrogates):
$s = "Hello, world! I 💖 you"
$sha256 = [System.Security.Cryptography.SHA256]::Create()
[BitConverter]::ToString(
$sha256.ComputeHash([System.Text.Encoding]::Unicode.GetBytes($s))
).Replace("-", "")
This yields the same result as
SELECT CONVERT(CHAR(64), HASHBYTES('SHA2_256', N'Hello, world! I 💖 you'), 2)

Try to update postgresql database using Doobie but no update happening

I'm trying to update table in postgresql database passing dynamic value using doobie functional JDBC while executing sql statement getting below error.Any help will be appreciable.
Code
Working code
sql"""UPDATE layout_lll
|SET runtime_params = 'testing string'
|WHERE run_id = '123-ksdjf-oreiwlds-9dadssls-kolb'
|""".stripMargin.update.quick.unsafeRunSync
Not working code
val abcRunTimeParams="testing string"
val runID="123-ksdjf-oreiwlds-9dadssls-kolb"
sql"""UPDATE layout_lll
|SET runtime_params = '${abcRunTimeParams}'
|WHERE run_id = '$runID'
|""".stripMargin.update.quick.unsafeRunSync
Error
Exception in thread "main" org.postgresql.util.PSQLException: The column index is out of range: 3, number of columns: 2.
Remove the ' quotes - Doobie make sure they aren't needed. Doobie (and virtually any other DB library) uses parametrized queries, like:
UPDATE layout_lll
SET runtime_params = ?
WHERE run_id = ?
where ? will be replaced by parameters passes later on. This:
makes SQL injection impossible
helps spotting errors in SQL syntax
When you want to pass parameter, the ' is part of the value passed, not part of the parametrized query. And Doobie (or JDBC driver) will "add" it for you. The variables you pass there are processed by Doobie, they aren't just pasted there like in normal string interpolation.
TL;DR Try running
val abcRunTimeParams="testing string"
val runID="123-ksdjf-oreiwlds-9dadssls-kolb"
sql"""UPDATE layout_lll
|SET runtime_params = ${abcRunTimeParams}
|WHERE run_id = $runID
|""".stripMargin.update.quick.unsafeRunSync

Using csv record in string with Powershell [duplicate]

This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 4 years ago.
I am importing a .csv into a variable $user. I can then access each field using $user.ARN (for example). This works fine.
But then I need to build a string using this variable.
$SQLQuery = "USE Cardpresso INSERT INTO dbo.students (Name, ARN, CardNumber, isPrinted) VALUES('$DisplayName', $User.ARN , $CardNumber, 0);"
When I check what is inside the $SQLQuery variable, it holds the whole csv row inplace of $User.ARN.
USE Cardpresso INSERT INTO dbo.students (Name, ARN, CardNumber, isPrinted) VALUES('%%% %%%', #{FirstName=%%%; LastName=%%%; ARN=%%%; Group=%%%; Email=unknown#unknow.com; Pass=%%%; Site=%%%; CardNumber=}.ARN , 508, 0);
(The %%% are real data, just removed)
Why is the $User.ARN not just been replaced with the data from just that field, instead it is inputting the whole row?
Thanks
For a file "sample.csv" with contents:
name,age,gender
billy,22,M
suzie,26,F
mikey,19,M
Tez,22,F
I'm importing the CSV, and I'm crafting insert statements from each record:
$stuff = Import-Csv -Delimiter ',' -Path .\sample.csv
foreach ($thing in $stuff) {
echo "INSERT INTO Cardpresso.dbo.students (Name, Age, Gender) VALUES ('$(${thing}.name), $(${thing}.age), '$(${thing}.gender)');"
}
Live example...
Good luck.

powershell - get a keyword from query string

I'm learning PowerShell scripting & want to extract tableName from SQL Query String. For example, I've this query -
$q = "SELECT * FROM [TestDB].[dbo].Invoice_Details where Clientname='ABC'"
where I want to extract table name i.e. it should output this - Invoice_Details
Currently, I'm doing this with following working code -
$q1 = $q -split '\[dbo\]\.'
$q2 = $q1[1] -split ' where '
write-host $q2[0] #here I get it right (Invoice_Details)
But, sometimes the query may/ may not have bracketed names like - [TestDB].[dbo].
So, I want to optimize this code so that it will work even if query containing any combination of bracketed/ bracketless tableNames
Try something like this:
$res = ([regex]'(?is)\b(?:from|into|update)\s+(\[?.+\]?\.)?\[?(\[?\w+)\]?').Matches($q)
write-host $res[0].Groups[2].Value

Output file using ISQL

Already I have a ISQL script working with Interbase that works with output into csv and I want to do the same thing to another type, but is not for example the first code works and it works . But the second one using Join statement is only working in the sql window, but could not output it.
Working :
OUTPUT TESTING1.csv FORMAT ASCII DELIMITED BY ';' QUOTE '';
Select * from aircraft;
OUTPUT;
Not working :
OUTPUT TESTING1.csv FORMAT ASCII DELIMITED BY ';' QUOTE '';
SELECT * FROM aircraft
Join Operation ON aircraft.AC_ID = Operation.ac_ID
OUTPUT;
I got it working now realise that I need to put the semi colon after the join statement:
OUTPUT TESTING1.csv FORMAT ASCII DELIMITED BY ';' QUOTE '';
SELECT * FROM aircraft
Join Operation ON aircraft.AC_ID = Operation.ac_ID;
OUTPUT;