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 FROM
Transact-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
'programing' 카테고리의 다른 글
의 개요Excel VBA의 Number Format 옵션 (0) | 2023.04.24 |
---|---|
Angular2 비활성화 버튼 (0) | 2023.04.24 |
여러 시트를 .pdf에 저장합니다. (0) | 2023.04.19 |
Swift에서 사전으로 플리스트를 얻으려면 어떻게 해야 하나요? (0) | 2023.04.19 |
Bash: 구문 오류: 리디렉션 예기치 않음 (0) | 2023.04.19 |