2017-05-25 96 views
1

我試圖從CSV文件中讀取值,將它們嵌入到INSERT T-SQL語句中,並使用Invoke-Sqlcmd運行該語句。將多個變量從csv文件傳遞到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 : The format used to define the new variable for Invoke-Sqlcmd cmdlet is invalid. Please use the 'var=value' format for defining a new variable.

的潛在空列是空或者包含單個數字編號1〜5。

I」中的所有列我嘗試了各種方法來轉義值,將其轉換爲不同的數據類型,向其中添加零或空字符串,null合併它,但我無法獲得可行的解決方案。

我有控制目標表,所以我很樂意爲空值傳遞零,空字符串,空或任何其他值作爲佔位符。

回答

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 
} 

因此,在每個循環過程中,我們使用格式運算符將列值插入到您的insert語句中。在屬性名稱中包含特殊字符時,在屬性名稱中使用花括號很有用。既然你只需要處理一個空間,引號也同樣適用。

我也想告訴你splatting這是一種將屬性作爲散列表傳遞給cmdlet的方法。這讓您可以即時編輯道具並縮短行距,而無需擔心隨處可見的反向。

+0

謝謝Matt。那種方法奏效了,」splatting「我覺得這樣會打開SQL注入攻擊的可能性,因此需要謹慎使用,但這在這種情況下不會成爲問題,我並不完全確定我的原始方法更好在這方面呢? – paulH

2

編輯 - 完全新的答案

我在ForEach-Object吸。這是一個foreach循環,用於檢查CSV中每行的「常規滿意度」值,並在完成$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 
} 
+0

感謝您的建議。我改變了腳本將命令放在一行上。這沒有效果。圍繞$ RowData變量添加引號會導致CSV中的每一行都失敗,並顯示我在問題中提到的錯誤消息。 – paulH

+0

但是,我認爲問題不在於$ RowData變量本身,它是爲Col2,Col3和Col4變量生成有效值。雖然我可能是錯的,因爲我無法解決這個問題! :-) – paulH

+0

謝謝。對,因爲它會把'$ RowData'強制轉換爲字符串 - 沒有發現。基於空字段引起的問題,也許最好的辦法是在'$ RowData ='部分中處理它......用'「Col1替換'」Col1 = $($ _。{My Ref})「'' =「」$($ _。{My Ref})「」「''修復它? – gms0ulman