花费更多时间在PowerShell中提取sql数据.遇到[System.DBNull] :: Value以及PowerShell在比较期间如何处理这些问题.
以下是我看到的行为示例以及变通方法
#DBNull values don't evaluate like Null... if([System.DBNull]::Value){"I would not expect this to display"} # The text displays. if([string][System.DBNull]::Value){"This won't display,but is not intuitive"} # The text does not display. #DBNull does not let you use certain comparison operators 10 -gt [System.DBNull]::Value # Could not compare "10" to "". Error: "Cannot convert value "" to type "System.Int32". Error: "Object cannot be cast from DBNull to other types."" [System.DBNull]::Value -gt 10 # Cannot compare "" because it is not IComparable. #No real workaround. Must use test for null workaround in conjunction to avoid comparison altogether: [string][System.DBNull]::Value -and [System.DBNull]::Value -gt 10 #Example scenario with a function that uses Invoke-sqlcmd2 to pull data Get-XXXXServer | Where-Object{$_.VCNumcpus -gt 8} #Error for every line where VCNumcpu has DBNull value #workaround Get-XXXXServer | Where-Object{[string]$_.VCNumcpus -and $_.VCNumcpus -gt 8}
我是否遗漏了任何内容,或者没有“简单”的解决方法可以让那些没有经验的人按预期使用PowerShell比较?
我提交了a suggestion on Connect并且有一个临时的workaround from Dave Wyatt,它将数据行转换为psobjects,并将dbnulls转换为空值,但是这个adds a bit of overhead.鉴于PowerShell现有的“松散”行为,这似乎应该在封面下处理?
任何提示,或者我现在已经用尽了我的选择?
谢谢!
解决方法
我觉得你在这里采取了错误的做法.作为
documented,DBNull类表示不存在的值,因此像-gt或-lt这样的比较没有任何意义.不存在的值既不大于也不小于任何给定值.但是,
Value
字段有一个Equals()方法,它允许您检查值是否为DBNull:
PS C:> ([DBNull]::Value).Equals(23) False PS C:> ([DBNull]::Value).Equals([DBNull]::Value) True