April 13, 2020 at 10:35 am
Hello Everyone!
I am working on a powershell script to centralize the history of all my sql jobs in a single table during insertion of the message column I have a problem with the apostrophe (see the print screen) Who can help me please
<#
Mahdouani Abdallah @2020
#>
Import-Module "SQLPS" -DisableNameChecking
Add-Type -AssemblyName "Microsoft.SqlServer.Smo"
Add-Type -AssemblyName "Microsoft.SqlServer.SmoExtended"
cd c:
$CollectServer = "DESKTOP-95KKMMH"
$collectDatabase = "msdb"
$serverList ="DESKTOP-95KKMMH","DESKTOP-95KKMMH\production"
foreach($svr in $serverList)
{
$servername = $svr
$sqlRec ="select @@servername as servername
,job.name
,run_time
,STUFF(
STUFF(STUFF(RIGHT(REPLICATE('0', 8) + CAST(run_duration AS VARCHAR(8)), 8), 3, 0, ':'), 6, 0, ':'),
9,
0,
':'
) 'duration'
,message
FROM sysjobhistory history
INNER JOIN sysjobs job
ON job.job_id = history.job_id
LEFT OUTER JOIN [dbo].[sysjobsteps] step
ON step.job_id = job.job_id
AND step.step_id = job.start_step_id
WHERE history.step_id = 0
AND CAST(dbo.agent_datetime(run_date, run_time) AS DATE) >= GETDATE() - 200
"
$result = Invoke-Sqlcmd -ErrorAction 'Stop' -ServerInstance $servername -query $sqlRec -database $collectDatabase
foreach($line in $result){
$insertReq =[String]::format(
"insert into msdb.dbo.History_job
(ServerName
,name
,run_time
,duration
,messsage)
values
('{0}','{1}','{2}','{3}','{4}')"
,@{$true="NULL";$false=($line.ServerName).ToString()}[$line.ServerName -eq [System.DBNull]::Value]
,@{$true="NULL";$false=($line.name).ToString()}[$line.name -eq [System.DBNull]::Value]
,@{$true="NULL";$false=($line.run_time).ToString()}[$line.run_time -eq [System.DBNull]::Value]
,@{$true="NULL";$false=($line.duration).ToString()}[$line.duration -eq [System.DBNull]::Value]
,@{$true="NULL";$false=($line.message).ToString() }[$line.message -eq [System.DBNull]::Value]
)
$insertReq = $insertReq.Replace("'NULL'","NULL")
Invoke-Sqlcmd -ErrorAction 'Stop' -ServerInstance $CollectServer -Database $collectDatabase -query $insertReq
}
}
April 13, 2020 at 11:43 am
you can do it 2 ways
1 - use parameters instead of string replacements - this is the best option- google and you will find some code with it for powershell
2 - for each variable you are passing to the format function replace ' by ''
April 13, 2020 at 1:50 pm
frederico_fonseca is correct, you should be using parameterized queries. Your current method is prone to SQL injection problems and you need to always account for those. Simply escaping strings (replacing ' with '') isn't really sufficient.
However, there's a much easier way to go about this using the dbatools module (https://dbatools/io). This module has functions which can extract the job history and then write it out to a table for you, including any "special character handling." It also has Invoke-DbaQuery which replaces Invoke-SqlCmd and can handle parameterized queries.
Get-DbaAgentJobHistory -SqlInstance $serverList | select-object sqlinstance, job, rundate, runduration,message | Write-DbaDataTable -SqlInstance $CollectServer -database $CollectDatabase -Table History_job -schema dbo -AutoCreateTable
You can insert some additional filtering in the pipeline where necessary, or set an "oldest date" via the -StartDate parameter for Get-DbaAgentJobHistory. It looks like you're restricting the history to anything newer than a particular point in time, but it's unclear what's happening when you subtract an integer from a datetime (>= GETDATE() - 200) - please use dateadd()!
If you can't use dbatools, please switch to the sqlserver module. It superseded sqlps 4 years ago.
Viewing 3 posts - 1 through 2 (of 2 total)
You must be logged in to reply to this topic. Login to reply