ole-objekt
Goto Top

Invoke-sqlcmd und Zellen mit null-Wert

Hallo!
Ich verzweifle seit 2 Tagen an invoke-sqlcmd, habe gefühlt schon das gesamte internet leer gelesen und kann mir nicht vorstellen, dass ich der erste mit diesem Problem bin und das noch niemand gelöst hat:

invoke sqlcmd liefert keine Null-Werte, d.h. wenn das Feld in der Datenbank null enthielt, habe ich jetzt eine leere Zelle in der Ergebnis-Tabelle (genau gesagt in der row-collection). Ich muss aber in der letztlich zu erstellenden Date null haben, weil die Datei in ein System hochgeladen werden soll, das leere Zellen nicht akzeptiert.

Mein bisheriger Code:

$dbResult = Invoke-Sqlcmd -Query $Sql -ConnectionString $global:ConStr -OutputAs DataTables
$dbResult | forEach-Object {
     foreach ($dbColumn in $dbResult.Columns) { 
          if  ($_.Item($dbColumn).ToString().Length -eq 0) { 
               'null'   
          } else { $_.Item($dbColumn) }
     }
} | Export-CSV -path $sTempFile -NoTypeInformation -Encoding $oWork.Encoding -UseCulture -UseQuotes Never

Ich versuche also, die einzelnen Zeilen (und darin die einzelnen Spalten) durchzugehen, die leeren Zellen zu erkennen und ggf 'null' zu setzen. Beim Debuggen des Codes sehe ich auch, dass die Erkennung funktioniert. Aber
1. erscheint in der entstehenden Datei keine null
2. ist die entstehende Datei total falsch. Statt 40 Spalten mit 16000 Zeilen gibt es eine Spalte mit 700000 Zeilen (alles ca.). Ohne den Versuch, durch die Zeilen und Spalten zu gehen, entsteht eine Datei im korrekten Format.

Ich würde mich freuen, wenn mir jemand
a) sagen würde, wo mein Code falsch ist oder
b) einen ganz anderen Ansatz liefern könnte.

Herzlichen Dank schonmal im Voraus,
Olaf

Content-Key: 63708510548

Url: https://administrator.de/contentid/63708510548

Printed on: April 29, 2024 at 18:04 o'clock

Mitglied: 12168552861
Solution 12168552861 Apr 13, 2024, updated at Apr 14, 2024 at 05:32:27 (UTC)
Goto Top
Teste mal (habe gerade kein Zugriff auf Invoke-SQLCmd
$dbResult = Invoke-Sqlcmd -Query $Sql -ConnectionString $global:ConStr -OutputAs DataTables
$result = foreach($entry in $dbResult.Rows){
     $new = [ordered]@{}
     foreach($dbColumn in $dbResult.Columns){
         $new.$dbcolumn = $entry[$dbColumn]
         if ($entry[$dbColumn] -in @([system.dbnull]::Value,$null,'')){  
            $new.$dbcolumn = 'null'  
         }
     }
     [pscustomobject]$new
}
If($result){
    $result | Export-CSV -path $sTempFile -NoTypeInformation -Encoding $oWork.Encoding -UseCulture -UseQuotes Never
}
https://tio.run/##fZAxb8IwEIX3/AoPkexIJgsbElJQKzY6tBVLlMGJD5HWsZHtNEWI35 ...

Gruß
Member: ole-objekt
ole-objekt Apr 13, 2024, updated at Apr 18, 2024 at 11:14:14 (UTC)
Goto Top
<edit: Nach Überarbeitung der Antwort von meisterroehrich ist dieser Kommentar eigentlich hinfällig, ich lösche ihn wegen des brute-force-Ansatzes dann trotzdem nicht.>

Hallo Meister Röhrich,

funktioniert eigentlich, allerdings bekomme ich einen Fehler bei numerischen Spalten, dass 'null' nicht erlaubt sei. Im Ergebnisset kann ich auch den DataType nicht mehr zu char ändern, die Fehlermeldung heißt "Cannot change DataType of a column once it has data." Klingt ja irgendwie auch verständlich...

Ein anderer Ansatz war, das Ergebnis nicht in die endgültige Datei zu schreiben, sondern erstmal in eine temporäre. In dieser kann dann mittels
Get-Content -Encoding $oWork.Encoding $sTempFile | foreach-object {$_.replace('""','null').Replace(',,',',null,').Replace(';;',';null;').Replace('-1',';null;').Replace(';,000',';null;')} | Out-File -FilePath $sExportFile -Encoding $oWork.Encoding   
das null nachträglich eingefügt werden. Bei mehreren aufeinander folgenden leeren Spalten wird allerdings nur jede zweite gefunden. D.h. ich habe das ganze jetzt mit einem brute force Ansatz gelöst:
Das Kopieren und ersetzen erfolgt zwei Mal hintereinander (!) wie oben beschrieben (von sTempFile zu sTempFile1, dann von sTempFile1 zu sTempFile2). Dann erfolgt es noch ein drittes Mal mit
Get-Content -Encoding $oWork.Encoding $sTempFile2 | foreach-object {$_ -replace ';$',';null'} | Out-File -FilePath $sExportFile -Encoding $oWork.Encoding   
um die letzte Spalte auch noch zu erwischen. Das ist zwar nicht schön, funktioniert aber. Falls noch jemandem eine elegantere Variante einfällt, freue ich mich auf weitere Ideen.

Herzlichen Dank für den Input und schöne Grüße an Frau Hansen!
Olaf
Mitglied: 12168552861
Solution 12168552861 Apr 14, 2024 updated at 05:43:35 (UTC)
Goto Top
Moin.
Nee lass das mit dem Replace das ist Humbug. Habe es oben entsprechend angepasst, sollte jetzt kein Problem mehr darstellen.

schöne Grüße an Frau Hansen!
Likörchen geht immer, näch 😂.
Member: wiesi200
wiesi200 Apr 14, 2024 at 15:34:30 (UTC)
Goto Top
Hallo,

und wenn du innerhalb deiner SQL Query das Problem schon angehst? Dafür gibt's "ISNULL"
Member: em-pie
em-pie Apr 14, 2024 at 20:45:55 (UTC)
Goto Top
Moin,

Ich muss aber in der letztlich zu erstellenden Date null haben, weil die Datei in ein System hochgeladen werden soll, das leere Zellen nicht akzeptiert.
Kannst du doch mittels des Ansatzes des Kollegen @wiesi200 Kompensieren:
Numerische und nicht numerische Felder fängst du im Query mit folgendem ab:
Select 
  ISNULL(table.myInteger, 0) as myInteger
  , ISNULL(table.myString, '') as myString   
FROM table
Legt Join anotherTable on blablabla

Dann erhältst du kein NULL (was bei einem CSV-Export sogar Mist wäre) sondern eine 0 bzw. ein Feld mit einem leeren Inhalt (was != Null ist).

Wir haben auch solch ein System und kompensieren das damit. Macht das Query zwar „länger“, aber das ist Wurscht. Sieht ja keiner aus uns Admins/ DBAs face-smile
Member: ole-objekt
ole-objekt Apr 18, 2024 at 11:11:15 (UTC)
Goto Top
Der angepasste Code von meisterroehrich löst mein Problem und ist zu allem Überfluss auch schön schnell. Herzlichen Dank dafür!

Die Vorschläge von wiesi200 und em-pie helfen mir leider nicht weiter.
1. Bei einer Integer-Spalte kann ich im isnull nicht den Wert 'null' setzen, weil der ja kein Integer ist.
2. Statt 'null' eine 0 zu schreiben, wäre bei Bool-Spalten eine Veränderung der Bedeutung von "unbekannt" zu "nein"
Member: wiesi200
wiesi200 Apr 18, 2024 at 11:22:35 (UTC)
Goto Top
Member: em-pie
em-pie Apr 18, 2024 at 11:30:56 (UTC)
Goto Top
Moin,

1. Bei einer Integer-Spalte kann ich im isnull nicht den Wert 'null' setzen, weil der ja kein Integer ist.
Du sollst ja auch 0 und nicht NULL einsetzen! Schaue bitte, was ISNULL() macht

2. Statt 'null' eine 0 zu schreiben, wäre bei Bool-Spalten eine Veränderung der Bedeutung von "unbekannt" zu "nein"
Bei Spalten mit Bool nimmt man ja dann auch True/ False
https://www.sqlshack.com/sql-boolean-tutorial/
Member: ole-objekt
ole-objekt Apr 19, 2024 at 23:39:26 (UTC)
Goto Top
Meine Anforderung ist aber, bei einem null-Wert in der Datenbank dann den Wert "null" in der entstehenden csv-Datei zu haben. Ursprünglich wurde dann ein leeres Feld exportiert. Und wenn ich statt null 0 setze, ändere ich die Bedeutung.
Und ja, eigentlich würde man bei Bool true/false setzen. Wir haben hier aber "aus historischen Gründen" tinyint-Spalten, in denen dann nur 0 oder 1 vorkommen darf - und null.
Aber die Sache ist ja nun dank meisterroehrich gelöst. Hier sind keine weiteren Antworten mehr nötig
Member: wiesi200
wiesi200 Apr 20, 2024 at 02:27:44 (UTC)
Goto Top
Ich persönlich hätte dann DB seitig vielleicht sogar 0,1,2 gearbeitet und keinen Nullwert zugelassen.

0 = unbekannt
1 = ja
2 = nein

Aber eher Geschmackssache und stark Situations und Tageslaunenabhängig