source

시스템을 다루고 있습니다.PowerShell에서 DBNull

ittop 2023. 10. 14. 10:38
반응형

시스템을 다루고 있습니다.PowerShell에서 DBNull

편집: 파워쉘 7 미리보기 2 현재,-not [System.DBNull]::Value에 평가합니다.$true, Joel Sallow 덕분에 pull request 9794.

PowerShell에서 SQL 데이터를 가져오는 데 더 많은 시간이 소요됩니다.[시스템]에서 문제가 발생했습니다.DBNull]::가치 및 비교 시 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 비교를 사용할 수 있는 '간단한' 해결책이 없는 것입니까?

Connect에 대한 제안서를 제출했고 Dave Wyatt로부터 dbnulls가 nulls로 변환된 데이터 행을 psobject로 변환하는 임시 해결책이 있지만 이로 인해 약간의 오버헤드가 발생합니다.PowerShell의 기존 '느슨한' 행동을 고려할 때 커버 아래에서 다루어야 하는 것처럼 보입니까?

조언 좀 해 주시겠어요? 아니면 제가 선택할 수 있는 것들을 다 써버린 건가요?

가장 간단한 방법은$var -isnot [DBNull].

제가 직접 스크립트로 테스트해봤는데 예상대로 작동합니다.

당신은 여기서 잘못된 접근을 하고 있는 것 같습니다.문서화된 바와 같이,DBNull클래스는 존재하지 않는 값을 나타내므로 다음과 같은 비교를 수행합니다.-gt아니면-lt말도 안 되는 소리.존재하지 않는 값은 어떤 주어진 값보다 크거나 작지 않습니다.필드에는 다음이 있습니다.Equals()값이 다음 값인지 여부를 확인할 수 있는 method입니다.DBNull:

PS C:> ([DBNull]::Value).Equals(23)
False
PS C:> ([DBNull]::Value).Equals([DBNull]::Value)
True

제가 보통 하는 일은 다음과 같습니다.

[String]::IsNullOrWhiteSpace($Val.ToString())

또는 이것:

[String]::IsNullOrEmpty($Val.ToString())

또는 이것:

$Val.ToString() -eq [String]::Empty

이는 종종 정상적으로 작동합니다.[System.DBNull]::Value.ToString()빈 문자열을 반환하므로 둘 다[String]::IsNullOrWhiteSpace([System.DBNull]::Value)그리고.[System.DBNull]::Value.ToString() -eq [String]::EmptyTrue로 평가합니다.

당연히 데이터에 빈 문자열이 있을 수도 있고, 빈 문자열(예: 정수)로 이해할 수 없는 데이터 유형일 수도 있기 때문에 논리적으로 동등하지 않습니다.그러나 DBNulls를 빈 문자열 및 공백 전용 문자열과 동일한 방식으로 처리하려는 경우가 많기 때문에 데이터를 충분히 알고 있는 경우 유용할 수 있습니다.

값이 DBNull인지 실제로 알고 싶다면 다음을 사용합니다.[DBNull]::Value.Equals($Value).

if( %youfunctetc%.GetType().Name -eq 'DBNull')
{}
else {}

PSI에서 SQL 데이터를 처리할 때 다음 기능을 포함하고 필요할 때 호출합니다.

function Check-IsNullWithSQLDBNullSupport ($var) {
    if ($var -eq [System.DBNull]::Value -or $var -eq $null) {
        return $true
    } else {
        return $false
    }
}

다음과 같이 사용할 수 있습니다.

if (Check-IsNullWithSQLDBNullSupport -var $VarToBeTested) {
    write-output "Is Null"
}

some-command | 여기 FieldOf Interest - is DBNull이 제게 적합한 것 같습니다.DBNull이 'type'이고 -is 연산자가 왼쪽의 값이 지정된 'type'인지 확인하고 있습니다.

또한 상대 some-command | 여기서 FieldOf Interest - is not DBNull을 사용할 수 있습니다.

예전 게시물에 대해서만 댓글을 다는 것 같은데, 위에서 데이브 와이엇과의 토론 링크가 끊어진 것 같아요. 구글링을 다시 해보니 여기서 찾았어요.

현재 작업 중인 코드는 성능에 민감하지 않지만 반환 데이터를 비교하여 다른 유형의 대상 개체의 속성을 재설정해야 합니다.

일반적으로 다음과 같은 편리한 PowerShell:

If( $SrcObject.Property ) { $TargObject.Property = $SrcObject.Property }

[DBNull]에서는 작동하지 않습니다.

보통 필요나 복잡성에 관계없이 가장 빠른 코드를 사용하고 검색/개발하는 데 시간이 걸리지만 최대한 빨리 rev1을 꺼내야 합니다.도 전에 [DBNull]하여 [PSCustomObject]다를 .| Select $Props

$Props는 열 이름을 타이핑한 배열입니다.그러나 하위 속성의 유형은 변경되지 않으므로 비교가 여전히 실패합니다!

데이브가 제안한 길을 이미 지나갔으니, 난 좀 더 질질 끌었어요.

$Props = ( $SQLData.Tables[0].Rows[0] | Get-Member -MemberType Properties ).Name
$Rows  = $SQLData.Tables[0].Rows | Select $Props

ForEach( $RowObject in $Rows )
{
    ForEach($Prop in $Props )
    {
        # Maybe: [String]::Empty below?
        If( $RowObject.$Prop -is [DBNull] ) { $RowObject.$Prop = "" }
    } #End Inner Loop.
} #End Outer Loop.

참고: prod 코드에 사전에 저장된 행이 있기 때문에 약간의 psuedo이지만 접근 방식을 전달하기에 충분할 것입니다.또한 위의 내용은 워킹 코드에서 번역한 것이기 때문에 충분히 테스트되지 않았습니다.

Get-Member가 RowError, RowState 등의 다른 속성을 반환하지 않는 이유를 모르겠습니다.하지만 [DBNull]의 파일을 빈 문자열로 변환해도 상관없는 한 이 작업은 가능합니다.그리고 겟멤버는 좀 더 재사용이 가능하고 소품을 입력할 필요가 없습니다.

분명히 이것은 앞서 언급한 몇몇 캐스팅과 크게 다르지 않지만, 도우미 기능에 있어서 복잡함을 주차하고 싶은 것은 저 혼자가 아닐 것이기 때문에 "메인"이 조금 더 깨끗해 보입니다.또한 빈 문자열은 나중에 대부분의 비교를 만족시켜야 하며, 특히 배경에서 진행되는 유형 변환 항목을 고려해야 합니다.

질문이 아닌 댓글인 건 알지만, 제가 틀린 게 있으면 말씀해주세요.저는 활동적인 프로젝트를 하다가 우연히 발견했습니다.감사합니다!

언급URL : https://stackoverflow.com/questions/22285149/dealing-with-system-dbnull-in-powershell

반응형