SQL Unclosed quotation error in PowerShell - sql-server

I have a small PowerShell Script that uploads CSV files to my SQL Server database using the Invoke-Sqlcmd command. It's working fine if the CSV file is small but I'm getting this error if the file has over 10,000 records.
Unclosed quotation mark after the character string.
I though the error is something else but it weird that it's working fine if I test with smaller size csv file.
$CSVImport = Import-CSV $PNP_CSV
ForEach ($CSVLine in $CSVImport) {
$CSVItemID = $CSVLine.ItemId
$CSVItemPath = $CSVLine.Path
$query = "USE $Global:Database
INSERT INTO PNP_Main (ItemId, ItemPath)
VALUES('$CSVItemID', '$CSVItemPath');"
Invoke-Sqlcmd -Query $query -ServerInstance $Global:Server -Database $Global:Database
}
Any help or suggestion would be really appreciated.

Related

Powershell invoke-sqlcmd sees hash as System.Byte[]

Currently i am trying to retrieve a query hash from a database. The plan is to query slow queries from the query store and write them to a csv file. To retrieve the data fro the database I am using the following command:
$queryResult = Invoke-Sqlcmd -ServerInstance $SQLServer -Database $SQLDatabase -InputFile $SQLQueryPath -Username $SQLUser -Password $SQLPassword -ConnectionTimeout 60 | Export-Csv $ResultPath -Delimiter "," -NoTypeInformation
The query used retrieves queries that are running slow with their query hash (stored in the query_hash field). This query is tested on the same database using SMSS and then it returns the hash field shown as a hash. This hash is stored in the sql database, it is not generated by the query or script.
But whenever I try to retrieve the query hash using Invoke-Sqlcmd it returns the query_hash field as a byte array (System.Byte[]). All other fields are shown as in SMSS. Tried printing the result in the powershell terminal but there it also shows me an array of bytes.
How can I get the script to return the hash?
Tried to use [System.Text.Encoding]::ASCII.GetString($.query_hash) and [System.Text.Encoding]::UTF8.GetString($.query_hash) but they expect a single byte where this script gives an array.

How to delete record from database if no longer existed

If I have a new data/record in my CSV file then I'm importing it to my SQL Server database using PowerShell like this.
$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.Hold
$CSVGSID1 = $CSVLine1.GSID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
$CSVCreatedDate1 = $CSVLine1.Time
$query = "USE $Global:Database
IF NOT EXISTS (SELECT * FROM Lit_Hold_Err
WHERE GSID = '$CSVGSID1'
AND Source = '$($CSVSource1 -replace "'","''")')
BEGIN
INSERT INTO Lit_Hold_Err (Hold, GSID, Source, Error, Type,Date)
VALUES('$CSVHold1', '$CSVGSID1', '$($CSVSource1 -replace "'","''")','$CSVMessage1','$CSVTYPE1', '$CSVCreatedDate1')
END"
Invoke-Sqlcmd -Query $query -ServerInstance $Global:Server -Database $Global:Database
I'm just wondering how should I write another query that compare my CSV file with my database and delete a particular/s record from my database if it's no longer existed in my CSV file?.
I know I'll need to use DELETE Statement but I'm kinda stuck on WHERE Clause so Any help or suggestion would be really appreciated.
A suggestion would be using DBATool's Import-DbaCsv to read the CSV file and bulk load it to a table on tempdb, then use a merge instruction to make the inserts/updates/deletes.
The import command would be something like:
$Credential = Get-Credential
Import-DbaCsv -Path .\test.csv -AutoCreateTable -SqlInstance my-instance -Database tempdb -SqlCredential $Credential -SupportsMultiline

Passing Powershell variable into a SQL INSERT

I'm quite new when it comes to Powershell and I'm not sure if my method is the best.
How can I pass Powershell variables into SQL using Invoke SQL or the .Net method? All I'm trying to do is to Insert data from the Get-AzureADGroup Display Name and Object Id into a SQL table.
$Groups = Get-AzureADGroup -All $true
foreach($Group in $Groups){
$DN = $Group.DisplayName
$ID = $Group.ObjectId
$insertquery="
INSERT INTO [dbo].[Table]([DsiplayName],[ObjectId])
VALUES(''$DN'',''$ID'')
"
Invoke-Sqlcmd -ServerInstance "Server" -Database "Database" -Query $insertquery
}
However, it comes up with the error 'Incorrect syntax near 'GroupDisplayName'. I've tried using " and ' interchangeably in the query with no luck. Am I missing something?

Invoke-Sqlcmd ran SQL script capture verbose output

I need to do health check on various servers on daily basis. I have SQL script which includes missing indexes, duplicate indexes, CPU and memory, recovery, failed job, last backup etc in one script.
I am running this script manually on sever and changing result to text (I have made script which use print statement so I can directly copy and paste result).
Now I want to run this script with PowerShell but I am not getting result to text format with row-column format.
Code:
$RESULT = (Invoke-Sqlcmd -InputFile $sqlscript -ServerInstance $server -Database $databse -Verbose 4>&1) |
Out-File $outfile
I am getting all the print statement but not the result in text file.
A more appropriate way to do this is as follows.
[string]$SqlsSript = '..\path\'
[string]$ConnectionString = '...'
$DataSet = Invoke-SqlCmd -ConnectionString $Connectionstring -InputFile $SqlScript -As DataSet
You can then explore the $DataSet collection, i.e
$DataSet.Tables[0].Rows
Which you can then transform / output to a file if you like.
Do ensure that your SqlScript returns a table, e.g. a table variable.

Powershell - Output SQL Messages to file

I have a Powershell script that invokes a saved SQL Query file and runs it on a specific Server & Database. That part is working well, the issue is that I would like to save the SQL Messages that it generates to a log file (see picture).
SQL Output from after Query is run
This is not working with my current code, and I believe that's because since it's technically not Query output but instead reindexing and updating tables, not fetching data.
My current relevant code is:
{
Import-Module SQLPS
$Data = Invoke-Sqlcmd -InputFile $SQLQuery -ServerInstance $Server -Database $Database -QueryTimeout 0
$Data | out-file "$Output$Database$date.txt"
}
But that just generates an empty text file. I'm looking to get the info on rebuilding indexes and the updates it's doing saved off into a different file through Powershell. You can do this through SSMS by right clicking in the Messages window and clicking "Save Results As..." but looking to include this in my automation since it's running as a Scheduled Task and no one is on SSMS.
Powershell v3/Windows Server 2012/SQL SSMS 2014
Any help would be appreciated!! This is my first post so sorry for odd formatting.
It looks like the following link explains exactly this problem:
https://sqlnotesfromtheunderground.wordpress.com/2015/09/09/powershell-outputting-a-sql-server-query-result-from-the-message-tab/
Essentially, what you are seeing in the 'Messages' tab are not results from the query, but rather just PRINT statements (essentially the same as Write-Host or Console.WriteLine). If you use Invoke-SqlCommand2, its -Verbose option will capture these PRINT statements to the Verbose PowerShell stream. To then write this stream to a text file, you have to specify the specific stream (in this case, 4):
Invoke-Sqlcmd2 -ServerInstance . -Database master -Query "PRINT 'Export This result'" -Verbose 4> Out-File C:\Temp\Test.txt
I had the same issue but instead in powershell script i use it in a command and i used -verbose.
like this
Invoke-Sqlcmd -ServerInstance '.\Your_server_instance' -Database 'DATABASE_Name' -InputFile "D:\Your_script.sql" verbose 4> "C:\sql\YOUR_OUTPUT_FILE.txt"
so i think this code should work for you
{
Import-Module SQLPS
$Data = Invoke-Sqlcmd -InputFile $SQLQuery -ServerInstance $Server -Database $Database -QueryTimeout 0
$Data -verbose *> "$Output$Database$date.txt"
}
for -verbose *> it streams All output you can redirect specific streams :
1 Success output
2 Errors
3 Warning messages
4 Verbose output
5 Debug messages

Resources