2017-05-25 3 views
1

Ich versuche, Werte aus einer CSV-Datei zu lesen, sie in eine INSERT T-SQL-Anweisung einzubetten und diese Anweisung mit Invoke-Sqlcmd auszuführen.Übergabe mehrerer Variablen aus der CSV-Datei an invoke-sqlcmd

Hier ist mein Code:

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 
    } 

Das Skript arbeitet für die Zeilen in der CSV-Datei in Ordnung, die Werte für jede Spalte enthalten. Leider enthalten einige Zeilen in der CSV-Datei leere Werte (daher enthalten möglicherweise nur die ersten beiden Spalten Werte). Diese Zeilen nicht eingefügt in die Tabelle werden, und erzeugen die folgenden Fehler:

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.

Die möglicherweise leere Spalten sind alle Spalten, die entweder leer oder enthalten eine einstellige Zahl 1 bis 5.

sind I‘ Ich habe verschiedene Möglichkeiten ausprobiert, um den Wert zu umgehen, ihn in einen anderen Datentyp umzuwandeln, ihm eine Null oder eine leere Zeichenfolge hinzuzufügen, null koaleszieren, aber ich kann keine Lösung finden, die funktioniert.

Ich habe die Kontrolle über die Zieltabelle, so würde ich gerne Null, leere Zeichenfolge, null oder einen anderen Wert als Platzhalter für die leeren Werte übergeben.

Antwort

2

Gemäß der Dokumentation Sie sind Variablen übergeben in einem String-Array, wobei jedes Element ein „Schlüssel = Wert“ Format hat. Sie bauen das richtig auf. Invoke-SQLCMD scheint Anstoß zu Null-Werte zu nehmen, die übergeben werden. Die Nullen kommen natürlich von leeren Einträgen in Ihrer CSV. Angenommen, Sie lassen Nullen in diesen Spalten zu, dann könnten Sie vielleicht die Abfrage anpassen, wenn die einzelnen Schleifen durchlaufen werden.

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 
} 

Also verwenden wir bei jedem Schleifendurchlauf den format-Operator, um die Spaltenwerte in Ihre insert-Anweisung einzufügen. Die Verwendung geschweifter Klammern in Eigenschaftsnamen ist nützlich, wenn Ihre Eigenschaften Sonderzeichen enthalten. Da musst du nur mit einem Leerzeichen umgehen; Zitate funktionieren genauso gut.

Ich wollte Ihnen auch splatting zeigen, eine Methode, um Eigenschaften als Hashtabelle an ein Cmdlet zu übergeben. So können Sie Requisiten im Handumdrehen bearbeiten und Ihre Linien kürzer halten, ohne dass Sie sich überall um Backticks kümmern müssen.

+0

Danke Matt. Dieser Ansatz funktioniert, und" splatting " Ich denke, dies eröffnet die Möglichkeit von SQL-Injection-Angriffen, so dass es mit Vorsicht verwendet werden muss, aber das stellt in diesem speziellen Fall kein Problem dar. Ich bin mir nicht ganz sicher, ob mein ursprünglicher Ansatz besser war aber in dieser Hinsicht? – paulH

2

Bearbeiten - völlig neue Antwort

ich ForEach-Object saugen. Dies ist eine foreach Schleife, die den Wert von "General staifaction" für jede Zeile in der CSV überprüft und durch eine Platzhalterzeichenfolge ersetzt, bevor die Variable $RowData abgeschlossen wird. Leider kann ich es hier nicht testen; Bitte lass mich wissen, wie es dir geht.

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

Danke für den Vorschlag. Ich habe das Skript geändert, um den Befehl auf eine einzige Zeile zu setzen. Dies hatte keine Wirkung. Das Angeben von Anführungszeichen um die Variable $ RowData führte dazu, dass jede Zeile in der CSV mit der in der Frage erwähnten Fehlermeldung fehlschlug. – paulH

+0

Ich glaube jedoch nicht, dass das Problem in der $ RowData-Variable selbst liegt, sondern darin, gültige Werte für die Col2-, Col3- und Col4-Variablen zu generieren. Obwohl ich darin vielleicht falsch liege, da ich das Problem nicht beheben konnte! :-) – paulH

+0

Danke. Richtig, weil es "$ RowData" als String ausgeben würde - das habe ich nicht bemerkt. Basierend auf dem Problem, das durch leere Felder verursacht wird, beschäftigt sich vielleicht der beste Ansatz damit in '$ RowData =' part ... Ersetzt '" Col1 = $ ($ _. {My Ref}) "' mit '" Col1 = "" $ ($ _. {Mein Ref}) "" "' fix it? – gms0ulman

Verwandte Themen