programing

T-SQL에서 둘 다 null일 수 있는 값을 비교하는 방법

elseif 2023. 4. 24. 22:33

T-SQL에서 둘 다 null일 수 있는 값을 비교하는 방법

테이블에 중복 행을 삽입하지 않도록 합니다(예: 기본 키만 다름).null을 "모든 값"으로 결정했기 때문에 모든 필드가 NULLS를 허용합니다.null로 인해 저장 프로시저의 다음 문이 작동하지 않습니다.

IF EXISTS(SELECT * FROM MY_TABLE WHERE 
    MY_FIELD1 = @IN_MY_FIELD1  AND
    MY_FIELD2 = @IN_MY_FIELD2  AND
    MY_FIELD3 = @IN_MY_FIELD3  AND 
    MY_FIELD4 = @IN_MY_FIELD4  AND
    MY_FIELD5 = @IN_MY_FIELD5  AND
    MY_FIELD6 = @IN_MY_FIELD6)
    BEGIN
        goto on_duplicate
    END

NULL = NULL이 아니기 때문입니다.

각 컬럼에 대해 IF IS NULL 스테이트먼트를 지정하지 않고 중복되는 것을 확인하려면 어떻게 해야 합니까?

@eric의 답변과 같은 행에 따라, 그러나 @eric의 답변은 사용하지 않습니다.'NULL'★★★★★★ 。

(Field1 = Field2) OR (ISNULL(Field1, Field2) IS NULL)

이는 두 값이 모두 다음과 같은 경우에만 해당됩니다.non-NULL 서로, 두 값 '어울리다'가 됩니다.NULL

연산자를 사용합니다.

입니다.NULL모든 필드에 복합 인덱스가 있는 경우 민감하고 효율적입니다.

IF      EXISTS
        (
        SELECT  MY_FIELD1, MY_FIELD2, MY_FIELD3, MY_FIELD4, MY_FIELD5, MY_FIELD6
        FROM    MY_TABLE
        INTERSECT
        SELECT  @IN_MY_FIELD1, @IN_MY_FIELD2, @IN_MY_FIELD3, @IN_MY_FIELD4, @IN_MY_FIELD5, @IN_MY_FIELD6
        )
BEGIN
        goto on_duplicate
END

「 」를하면,UNIQUE당신의 밭에 인덱스를 붙이면 당신의 삶은 훨씬 더 단순해질 것입니다.

MERGE를 실행할 때도 비슷한 비교가 필요했습니다.

WHEN MATCHED AND (Target.Field1 <> Source.Field1 OR ...)

모든 열이 이미 동일한 행이 업데이트되지 않도록 하기 위한 추가 검사입니다.내 목적을 위해 나는 원했다.NULL <> anyValue 참, 참이다, 참이다, 참이다NULL <> NULL거짓이다.

솔루션은 다음과 같이 진화했습니다.

첫 번째 시도:

WHEN MATCHED AND
(
    (
        -- Neither is null, values are not equal
        Target.Field1 IS NOT NULL
            AND Source.Field1 IS NOT NULL
            AND Target.Field1 <> Source.Field1
    )
    OR
    (
        -- Target is null but source is not
        Target.Field1 IS NULL
            AND Source.Field1 IS NOT NULL
    )
    OR
    (
        -- Source is null but target is not
        Target.Field1 IS NOT NULL
            AND Source.Field1 IS NULL
    )

    -- OR ... Repeat for other columns
)

두 번째 시도:

WHEN MATCHED AND
(
    -- Neither is null, values are not equal
    NOT (Target.Field1 IS NULL OR Source.Field1 IS NULL)
        AND Target.Field1 <> Source.Field1

    -- Source xor target is null
    OR (Target.Field1 IS NULL OR Source.Field1 IS NULL)
        AND NOT (Target.Field1 IS NULL AND Source.Field1 IS NULL)

    -- OR ... Repeat for other columns
)

세 번째 시도(@THEN의 답변에서 영감을 얻음):

WHEN MATCHED AND
(

    ISNULL(
        NULLIF(Target.Field1, Source.Field1),
        NULLIF(Source.Field1, Target.Field1)
    ) IS NOT NULL

    -- OR ... Repeat for other columns
)

동일한 ISNULL/NULLIF 로직을 사용하여 등식과 부등식을 테스트할 수 있습니다.

  • 등성::ISNULL(NULLIF(A, B), NULLIF(B, A)) IS NULL
  • 부등식:ISNULL(NULLIF(A, B), NULLIF(B, A)) IS NOT NULL

다음은 http://sqlfiddle.com/#!3/471d60/1의 구조를 보여주는 SQL-Fiddle입니다.

사용방법:

ISNULL(MY_FIELD1, 'NULL') = ISNULL(@IN_MY_FIELD1, 'NULL')

수 요.'NULL'과 같은 'All Values'그렇게 하는 것이 더 말이 된다면요.

인수가 있는 는, 「」라고 점에 해 주세요.ISNULL는 와 동일하게 동작합니다.테스트할 값이 몇 개 있는 경우에 사용할 수 있습니다(즉,COALESCE(@IN_MY_FIELD1, @OtherVal, 'NULL')COALESCE또한 첫 번째 null이 아닌 뒤에 반환됩니다.즉, MY_FIELD1이 비어 있을 것으로 예상되는 경우 (마지막으로) 더 빠릅니다.나는 지,, 는는을 발견한다.ISNULL훨씬 가독성이 높기 때문에 여기다가 썼어요.

IF EXISTS(SELECT * FROM MY_TABLE WHERE 
            (MY_FIELD1 = @IN_MY_FIELD1 
                     or (MY_FIELD1 IS NULL and @IN_MY_FIELD1 is NULL))  AND
            (MY_FIELD2 = @IN_MY_FIELD2 
                     or (MY_FIELD2 IS NULL and @IN_MY_FIELD2 is NULL))  AND
            (MY_FIELD3 = @IN_MY_FIELD3 
                     or (MY_FIELD3 IS NULL and @IN_MY_FIELD3 is NULL))  AND
            (MY_FIELD4 = @IN_MY_FIELD4 
                     or (MY_FIELD4 IS NULL and @IN_MY_FIELD4 is NULL))  AND
            (MY_FIELD5 = @IN_MY_FIELD5 
                     or (MY_FIELD5 IS NULL and @IN_MY_FIELD5 is NULL))  AND
            (MY_FIELD6 = @IN_MY_FIELD6
                     or (MY_FIELD6 IS NULL and @IN_MY_FIELD6 is NULL)))
            BEGIN
                    goto on_duplicate
            END

IFNULL/COALESCE 솔루션과의 비교.그러나 NULL의 스탠드로 사용할 수 있는 데이터에 어떤 값이 표시되지 않는지에 대해서는 생각할 필요가 없습니다.

각각의 값을 합칠 수는 있지만, 이는 약간 의기소침합니다.

    IF EXISTS(SELECT * FROM MY_TABLE WHERE 
    coalesce(MY_FIELD1,'MF1') = coalesce(@IN_MY_FIELD1,'MF1')  AND
    ...
    BEGIN
            goto on_duplicate
    END

, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 그리고coalesced해당 다른 .예를 들어, MY_FILD1의 값이 'MF1'일 수 있는 경우, 많은 수의 스플리어스 히트가 발생합니다.

동등 비교:

((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))

Not Equal To 비교: 위의 Equals 비교를 부정합니다.

NOT ((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))

장황한가요?네.하지만 기능을 호출하지 않기 때문에 효율적입니다.술어에서 단락을 사용하여 동일한 연산자(=)가 비표준 값에만 사용되도록 하는 것입니다. 그렇지 않으면 null이 식 트리에서 전파됩니다.

동일하지 않은 값을 비교하려면 어떻게 해야 합니까?앞서 언급한 비교 앞에 "NOT"를 사용하는 것만으로는 작동하지 않습니다.내가 생각해낼 수 있는 최선의 방법은:

(Field1 <> Field2) OR (NULLIF(Field1, Field2) IS NOT NULL) OR (NULLIF(Field2, Field1) IS NOT NULL)

필드에 프라이머리 키를 생성하여 엔진에 고유성을 적용합니다.어쨌든 IF ENSISTES 논리를 하는 것은 인종 조건에 결함이 있기 때문에 부정확하다.

하면 .SET ANSI_NULLS[ Equals ( = ) ] [ [ Not Equal To ( < > ) ]비 [ 、 [ Not Equal To ( < > ) 。

위의 @drowa는 내가 동의하는 장황한 접근을 보여준다.3값 논리 문제를 회피하기 때문에 좋습니다.하는 다른 될 때 치 않은 . 왜냐하면 이 접근법들을 치료하고 때문입니다.null와와 to to 에 상당하는 false하지만 그렇지 않아요

그러나 워크플로우가 있어 편리하다고 생각합니다.여기 정규식이 있습니다.폼의 특정 코드

(leftSide <=> rightSide)

regex는 다음을 찾습니다.

\(([a-zA-Z0-9_.@]+)\s*<=>\s*([a-zA-Z0-9_.@]+)\)

다음과 같이 바꿉니다.

(/*$1 <=> $2*/ ($1 IS NULL AND $2 IS NULL) OR ($1 IS NOT NULL AND $2 IS NOT NULL AND $1 = $2))

.(leftSide <=> rightSide)코드화하고 위의 regex 변환을 적용하여 확장 형식을 가져옵니다.MSQL에서 매크로 확장을 제공하므로 수동으로 작업을 수행할 필요가 없습니다.

@Drowa의 답변은 참고용으로 인용되었습니다.

동등 비교:

((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))

Not Equal To 비교: 위의 Equals 비교를 부정합니다.

NOT ((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))

장황한가요?네.하지만 기능을 호출하지 않기 때문에 효율적입니다.술어에서 단락을 사용하여 동일한 연산자(=)가 비표준 값에만 사용되도록 하는 것입니다. 그렇지 않으면 null이 식 트리에서 전파됩니다.

IS NULL 또는 ISNULL을 사용해야 합니다. 정말 멀리 떨어져 있지 않습니다.

NULLIF(TARGET.relation_id, SOURCE.app_relation_id) IS NULL Simple solution

SQL Server 2022부터의 "Null safe" 버전은

WHERE 
    MY_FIELD1 = @IN_MY_FIELD1  AND
    MY_FIELD2 = @IN_MY_FIELD2  AND
    MY_FIELD3 = @IN_MY_FIELD3  AND 
    MY_FIELD4 = @IN_MY_FIELD4  AND
    MY_FIELD5 = @IN_MY_FIELD5  AND
    MY_FIELD6 = @IN_MY_FIELD6

되지요

WHERE 
    MY_FIELD1 IS NOT DISTINCT FROM @IN_MY_FIELD1  AND
    MY_FIELD2 IS NOT DISTINCT FROM @IN_MY_FIELD2  AND
    MY_FIELD3 IS NOT DISTINCT FROM @IN_MY_FIELD3  AND 
    MY_FIELD4 IS NOT DISTINCT FROM @IN_MY_FIELD4  AND
    MY_FIELD5 IS NOT DISTINCT FROM @IN_MY_FIELD5  AND
    MY_FIELD6 IS NOT DISTINCT FROM @IN_MY_FIELD6

IS [NOT] DISTINCT FROMTransact-SQL)

NULLIF 확인하셨나요?http://msdn.microsoft.com/en-us/library/ms177562.aspx

언급URL : https://stackoverflow.com/questions/1075142/how-to-compare-values-which-may-both-be-null-in-t-sql