首页 > 解决方案 > 如何替换导致 SQL 语法错误的撇号

问题描述

预期行为:

  1. 有一个浏览文件目录并获取所有目录详细信息的 PS 脚本(工作)
  2. 将这些详细信息写回 SQL 表(工作)

该脚本正在运行,但失败并出现如下错误:

ForEach-Object:使用“0”参数调用“ExecuteNonQuery”的异常:“'EGIDIO' 附近的语法不正确”

我知道这是由撇号引起的。失败时读取的文件夹名为“D'EGIDIO, SHAH &TOWNSEND”。

问题是我似乎无法弄清楚如何在 PS 脚本中替换该文本,或者从脚本中插入 sql。无论我尝试什么它仍然失败。

#Invoke-sqlcmd Connection string parameters
$params = @{'server'='TESTServer';'Database'='_Maintenance'}
#Server to query WMI class win32_logicalDisks
$server = 'TESTServer'
#Prepare Insert Statement

$insert = @' 
    INSERT INTO [_PBS_Maintenance].[dbo].[Maint_DiskSpace](Path,SizeInMB,SizeInGB,FileLastModified,CreatedDate,CreatedBY)
    VALUES (
                '{0}',
                '{1}',
                '{2}',
                '{3}',
                GetDate(),
                SYSTEM_USER
           )
'@
 write-host $insert
Try {
    #Define connction string of target database
    $connectionString = 'Data Source=PBSNV800IMG1\PBSNV800IMG1;Initial Catalog=_PBS_Maintenance;Integrated Security=SSPI'
    # connection object initialization
    $conn = New-Object System.Data.SqlClient.SqlConnection($connectionString)
    #Open the Connection 
    $conn.Open()
    # Prepare the SQL 
    $cmd = $conn.CreateCommand()

    $array= @() 
    $folder = "\\fsvr\Public\Users\Valorie L\Valorie\ATTORNEY\EIC-ERMG\" 
    $Source = $folder

Get-ChildItem -Recurse $Source | Where-Object { $_.PSIsContainer } | 
    ForEach-Object { 
            $obj = New-Object PSObject  
            $SizeMB = [Math]::Round((Get-ChildItem -Recurse $_.FullName | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB, 2)
            $SizeGB = [Math]::Round((Get-ChildItem -Recurse $_.FullName | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1GB, 2)  
            $obj |Add-Member -MemberType NoteProperty -Name "Path" $_.FullName
            $obj |Add-Member -MemberType NoteProperty -Name "SizeMB" $SizeMB 
            $obj |Add-Member -MemberType NoteProperty -Name "SizeGB" $SizeGB 
            $obj |Add-Member -MemberType NoteProperty -Name "DateModified" $_.LastWritetime
                    $array +=$obj 


    select Path,SizeMB,DateModified
        ForEach-Object{
            $cmd.CommandText = $insert -f $obj.Path,$obj.SizeMB,$obj.SizeGB, $obj.DateModified
            $cmd.ExecuteNonQuery()
    }
}
    #Close the connection
    $conn.Close()

}
Catch {
    Throw $_
}

Invoke-Sqlcmd @params -Query "SELECT  * FROM Maint_DiskSpace" | format-table -AutoSize

标签: sql-serverpowershellreplaceexecutenonqueryforeach-object

解决方案


单引号在 SQL 中通过加倍来转义(两个单引号' ',而不是双引号")。在路径的情况下,您需要在这一行执行以下操作:

$obj |Add-Member -MemberType NoteProperty -Name "Path" $_.FullName

稍微修改一下,用两个单引号替换任何单引号,如下所示:

$obj |Add-Member -MemberType NoteProperty -Name "Path" ( $_.FullName -replace "'", "''" )

它的工作原理是我们 subexpress $_.FullName,因此我们可以使用-replace运算符将​​路径中的任何单引号替换为两个单引号。Path首先计算子表达式,然后将返回的值作为on 属性的值应用于父范围$obj


请注意,谨慎的做法是确保您转义文件夹路径中允许的所有字符,这些字符需要作为 SQL 查询的一部分进行转义,以及应该转义以防止 SQL 注入攻击的字符。


推荐阅读