1

我正在尝试从 CSV 文件中读取值,将它们嵌入到 INSERT T-SQL 语句中并使用 Invoke-Sqlcmd 运行该语句。

这是我的代码:

Push-Location; Import-Module SQLPS -DisableNameChecking; Pop-Location

$InsertQry = "insert into $ImportTable VALUES ('`$(Col1)','`$(Col2)','`$(Col3)','`$(Col4)') "

Import-CSV $ImportFile | ForEach-Object { `
$RowData = "Col1=$($_.{My Ref})","Col2=$($_.{General satisfaction})","Col3=$($_.Helpfulness)","Col4=$($_.Effort)"
    Invoke-Sqlcmd `
    -Database $DBName -ServerInstance $SQLServer `
    -Query $InsertQry `
    -Variable $RowData
  }

该脚本适用于 CSV 文件中包含每列值的行。对我来说不幸的是,CSV 文件中的某些行包含空值(因此可能只有前两列包含值)。这些行无法插入到表中,并生成以下错误:

Invoke-Sqlcmd :用于为 Invoke-Sqlcmd cmdlet 定义新变量的格式无效。请使用 'var=value' 格式定义新变量。

可能为空的列是所有为空或包含单个数字 1 到 5 的列。

我尝试了各种方法来转义该值,将其转换为不同的数据类型,向其添加零或空字符串,将其合并为空,但我无法获得有效的解决方案。

我可以控制目标表,因此我很乐意将零、空字符串、null 或任何其他值作为空值的占位符传递。

4

2 回答 2

2

编辑 - 全新的答案

我很讨厌ForEach-Object。这是一个循环,检查 CSV 中每一行的“General staisfaction”值,并在完成变量foreach之前将其替换为占位符字符串。$RowData不幸的是,我无法在这里测试它;请让我知道你过得怎么样。

Push-Location; Import-Module SQLPS -DisableNameChecking; Pop-Location

$InsertQry = "insert into $ImportTable VALUES ('`$(Col1)','`$(Col2)','`$(Col3)','`$(Col4)') "

$myCSVFile = Import-CSV $ImportFile 

foreach($line in $myCSVFile){

    if($line."General staisfaction" -eq $null -or $line."General staisfaction" -eq ""){
        $line."General staisfaction" = "placeholder"
    }

    $RowData = "Col1=$($line.{My Ref})","Col2=$($line.{General satisfaction})","Col3=$($line.Helpfulness)","Col4=$($line.Effort)"

    Invoke-Sqlcmd -Database $DBName -ServerInstance $SQLServer -Query $InsertQry -Variable $RowData
}
于 2017-05-25T15:54:31.937 回答
2

根据文档,您将在字符串数组中传递变量,其中每个元素都具有“key=value”格式。您正在正确地构建它。Invoke-SQLCMD似乎对传递的空值感到冒犯。空值当然来自 CSV 中的空白条目。假设您在这些列中允许空值,那么也许您可以在每个循环通过时调整查询。

Push-Location; Import-Module SQLPS -DisableNameChecking; Pop-Location

$InsertQry = "insert into $ImportTable VALUES ('{0}','{1}','{2}','{3}')"
$propertiesToSplat = @{
    Database = $DBName 
    ServerInstance = $SQLServer
}

Import-CSV $ImportFile | ForEach-Object {
    $propertiesToSplat.Query = $InsertQry -f $_."My Ref", $_."General satisfaction", $_.Helpfulness, $_.Effort
    Invoke-Sqlcmd @propertiesToSplat
}

因此,在每个循环传递中,我们使用格式运算符将列值插入到您的插入语句中。当您的属性包含特殊字符时,在属性名称中使用花括号很有用。因为你只需要处理一个空间;引号也可以。

我还想向您展示splatting,这是一种将属性作为哈希表传递给 cmdlet 的方法。这使您可以即时编辑道具并缩短行数,而不必担心到处都有反引号。

于 2017-05-25T16:36:37.017 回答