Mathias' answer explains the problem with the inefficiency of your first attempt well and offers a solution that ultimately performs best, due to use of a (single) foreach statement (as opposed to the much slower ForEach-Object cmdlet).
However, a solution using a (single) .Where() array method call (or the related .ForEach() method):
- is only slightly slower[1]
- while being more concise and arguably conceptually more elegant.
It is what you tried with $sqlimport.Where({ $_.col5 -eq '' }), which, based on your feedback, requires only one small tweak to make it work:
- Instead of
-eq '' use -like '', which is a somewhat obscure[2] shortcut to testing for an empty string ('') and also for a $null value (as also used in Mathias' answer) - it is, in essence, the equivalent of .NET's [string]::IsNullOrEmpty() method.
# -like matches both '' and $null
$sqlimport.Where({ $_.col5 -like '' })
Note:
If you wanted to test for $null values only, use the following; note how $null is placed on the LHS, which is generally advisable for robust comparisons[3]:
$sqlimport.Where({ $null -eq $_.col5 })
- As an aside: GitHub issue #10656 proposes introducing a simplified test for
$null with something like -is $null; unfortunately, the associated PR has been abandonded.
As an aside: [string]-type-constrained PowerShell variables never store $null values:
[string] $str = $null causes $str to contain '', not $null. However, [string]-typed property values not populated in PowerShell code can contain $null values, as in your case.
- For passing a true
$null value to a string-typed .NET API in PowerShell code, a special singleton must be used (passing $null directly would again result in ''): [NullString]::Value`
- See this answer for background information.
[1] For a performance comparison of PowerShell's various enumeration (iteration) features, see the bottom section of this answer.
[2] The real purpose of the -like operator is to perform wildcard-expression matching. The shortcut relies on
-like - which operates on (non-null) strings only - auto-converting non-string operands to strings, which in the case of $null causes conversion to '' (the empty string).
[3] To reliably test for $null, place it on the LHS of an -eq / -ne operation; e.g., $null -eq $var. If you place $null on the RHS - $var -eq $null - and $var happens to be a collection (such as an array), the return value is the array of matching elements, i.e. the array of those elements in $var whose value is $null, which is a different operation - see about_Comparison_Operators.