NULL의 <>! = 연산자와 같지 않음


271

누군가 SQL에서 다음 동작을 설명해 주시겠습니까?

SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)

답변:


309

<>표준 SQL-92입니다. !=동일합니다. 둘 다 값에 대해 평가합니다. 이는 값 NULL이 없다고 NULL말하는 자리 표시 자입니다.

그렇기 때문에 그러한 상황에서는 술어로 IS NULL/ 만 사용할 수 있습니다 IS NOT NULL.

이 동작은 SQL Server에만 국한되지 않습니다. 모든 표준 호환 SQL 언어는 동일한 방식으로 작동합니다.

참고 : 귀하의 경우에 비교하기 위해 값이 null이 아닌 , 사용 IS NOT NULL과 비교하면서, NOT NULL 값, 당신은 사용 <> 'YOUR_VALUE'. 내 값이 NULL인지 아닌지를 말할 수는 없지만 내 값이 NULL인지 NOT NULL인지 말할 수 있습니다. 내 값이 NULL 이외의 값인지 비교할 수 있습니다.


4
실제로, 그것은 <>92 사양에 있다고 생각 하지만 대부분의 공급 업체 지원 !=및 / 또는 99 또는 03과 같은 최신 사양에 포함되어 있습니다.
Thomas

2
@Thomas : Oracle은 !=~ 9i까지 지원하지 않았기 때문에 많은 ANSI-92 구문을 가져 왔습니다. 제 생각에는 MySQL은 4.x에서 지원을 시작하는 것과 비슷합니다.
OMG Ponies

그것은 !=의 대안으로 이후의 사양에 포함되었을 수 있다고 제안하는 것 같습니다 <>. 새로운 사양에 손을 대지 않아도 확실하게 말할 수는 없습니다.
토마스

2
의 결과인가 WHERE MyColumn != NULL또는 WHERE MyColumn = NULL결정? 즉, MyColumn데이터베이스에서 null을 허용 하는지 여부 에 관계없이 항상 0 행을 반환하는 것이 보장 됩니까?
Slauma

11
또한 !=값만 평가 하므로 WHERE MyColumn != 'somevalue'NULL 레코드를 반환하지 않는 것과 같은 작업을 수행 합니다.
jsumrall

88

NULL에는 값이 없으므로 스칼라 값 연산자를 사용하여 비교할 수 없습니다.

즉, NULL에는 값이 없으므로 값이 NULL과 같거나 같을 수 없습니다.

따라서 SQL에는 NULL을 처리하기위한 특수 IS NULL 및 IS NOT NULL 술어가 있습니다.


3
+1. 또한 OP 문과 달리 "Microsoft SQL"이 아닙니다. 삼항 논리는 SQL 표준에 정의되어 있으며이 시점에서 MS는 표준을 준수합니다.
TomTom

6
나는 이것이 Microsoft의 유일한 행동이라고 제안하지 않았다. Microsoft SQL Server에서이를 관찰했다고 간단히 말하고있었습니다.
Maxim Gershkovich

13
관심이 없다면,이 (예상 된) 행동이 유용한 상황이 있습니까? 그것은 'a' != null( true/ 1) 값을 반환하지 않는 것이 반 직관적이며 때때로 나를 잡아냅니다! 나는 "무가치에 비해 어떤 가치는"항상 "같지 않다"고 생각했지만 아마도 그저 나 일까?!?
DarthPablo

1
사람들이 NULL을 ' 값이없는 ' 것으로 묘사하는 것이 흥미 롭습니다 . 그렇다면 숫자 1이 실제로 값일 때 '값이있다'고 말하는 것과 비슷합니다. 그러나 NULL은
비값을

수동 해결 방법으로, 일반적으로 SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'상수가 NULL 값인 경우 센티넬 값 x (이 경우 문자열 / 문자열)에 적절한 데이터 유형을 제공하면 상수를 할당 할 수 있습니다. 이것은 TSQL 구문이지만 Oracle 및 기타 엔진에는 비슷한 기능이 있습니다.
systemaddict

26

이 동작은 기본 (ANSI) 동작입니다.

만약 너라면:

 SET ANSI_NULLS OFF

http://msdn.microsoft.com/en-us/library/ms188048.aspx

다른 결과를 얻을 수 있습니다.

SET ANSI_NULLS OFF 분명히 미래에 사라질 것입니다 ...


8
+1 ... 곧 충분하지 않습니다. 이제 인덱스에서 "중복"NULL을 언제 얻을 수 있습니까? :(

필터링 된 인덱스 (예 :)에 WHERE 절을 추가하여 SQL Server 인덱스에서 중복 NULL을 얻을 수 있습니다 create unique index UK_MyTable on MyTable (Column) where Column is not null. msdn.microsoft.com/en-us/library/cc280372.aspx
Anthony Mills

3
워드 프로세서에서 참고 : SET ANSI_NULLSOFF입니다, 같음 (=)과 같지 않음 (<>) 비교 연산자는 ISO 표준을 따르지 않습니다. 사용하는 SELECT 문 WHERE column_name = NULL은 column_name에 null 값이있는 행을 반환합니다. 사용하는 SELECT 문 WHERE column_name <> NULL은 열에 null이 아닌 값이있는 행을 반환합니다. 또한 사용하는 SELECT 문 WHERE column_name <> XYZ_value은 XYZ_value가 아니며 NULL이 아닌 모든 행을 반환합니다. IMHO,이 마지막 진술은 결과에서 null을 제외하는 데 약간 이상하게 보입니다!
DarthPablo 2016 년

4
msdn doc의 중요 참고 사항 : 향후 버전의 SQL Server (2014 이상)에서 ANSI_NULLS는 항상 ON이며 옵션을 명시 적으로 OFF로 설정 한 응용 프로그램은 오류를 생성합니다. 새로운 개발 작업 에서이 기능사용하지 말고 현재이 기능을 사용하는 응용 프로그램을 수정하십시오.
Otiel

7

SQL에서 NULL결과로 평가하고 계산하는 모든 것이 UNKNOWN으로

이런 이유로 SELECT * FROM MyTable WHERE MyColumn != NULL또는 SELECT * FROM MyTable WHERE MyColumn <> NULL당신에게 0 결과를 제공합니다.

NULL값을 확인하기 위해 isNull 함수가 제공됩니다.

또한 IS세 번째 쿼리에서 사용한 연산자를 사용할 수 있습니다 .

도움이 되었기를 바랍니다.


"SQL에서 NULL을 사용하여 평가 / 계산 한 결과는 'NULL'로 나타납니다."-올바르지 않습니다. 당신이 의미하는 결과는 알 수 없습니다.
1

@MahendraLiya isNull 함수는 NULLS를 검사하기 위해 제공되지 않지만 " NULL을 지정된 대체 값으로 대체합니다. ". ISNULL 대신 IS NULL 또는 IS NOT NULL을 사용해야합니다.
리버스 엔지니어

7

NULL에 대한 유일한 테스트는 IS NULL 또는 IS NOT NULL입니다. 정의에 따라 값이 무엇인지 모르기 때문에 평등 테스트는 의미가 없습니다.

읽을 위키 백과 기사는 다음과 같습니다.

https://en.wikipedia.org/wiki/Null_(SQL)


6

우리는 사용

SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';

MyColumn이 NULL 인 모든 행 또는 MyColumn이 빈 문자열 인 모든 행을 반환합니다. 많은 "최종 사용자"에게 NULL 대 빈 문자열 문제는 필요와 혼란이없는 구별입니다.


5

나는 null이 다른 값이나 다른 null과 비교할 수없는 기능적이고 완벽한 이유를 보지 못하므로 명확하게 비교하고 문맥 상 동일하거나 그렇지 않다고 말할 수 있습니다. 재밌 네요 논리적으로 결론을 내리고 일관성을 유지하기 위해 끊임없이 고민해야합니다. 그것은 기능적이지 않으며, 더 기능적으로 만들고 철학자와 과학자들에게 일관성이 있는지 아닌지를 결정하고 "유니버설 논리"를 유지하는지 결론을 내립니다. :) 누군가 색인이나 다른 이유로 인해 있다고 말할 수 있습니다. 값과 같은 null을 지원하도록 할 수 없었습니다. 그것은 두 개의 빈 안경을 비교하는 것과 같습니다. 하나는 포도 나무 유리이고 다른 하나는 맥주 유리입니다. 우리는 객체 유형을 비교하지 않고 int와 varchar를 비교할 수있는 것과 같은 값을 포함합니다. 더 쉽고, 아무것도 아니고 두 가지 공통점이있는 것은 동일합니다. 동일하고 SQL을 작성하는 다른 사람들과 동일합니다. 우리는 일부 ANSI 표준으로 인해 이상한 방식으로 논리를 비교하여 논리를 끊임없이 깨뜨리기 때문에 SQL을 작성하는 다른 사람들과 동일합니다. 컴퓨터 전원을 사용하여 우리를 위해 그것을하지 않는 이유는 무엇입니까? 관련된 모든 것이 그것을 염두에두고 구성되면 속도가 느려질 것입니다. "아무것도 null이 아닙니다", 사과가 아닙니다. apfel입니다. 기능적으로 여러분의 친구이며 여기에도 논리가 있습니다. 결국 중요한 것은 기능성이며, 그런 식으로 null을 사용하는 것은 기능성과 사용 편의성을 어느 정도 제공합니다. 더 유용합니까? ANSI 표준 때문에 이상한 방식으로 논리를 비교하여 논리를 끊임없이 깨뜨리고 있기 때문입니다. 컴퓨터 전원을 사용하여 우리를 위해 그것을하지 않는 이유는 무엇입니까? 관련된 모든 것이 그것을 염두에두고 구성되면 속도가 느려질 것입니다. "아무것도 null이 아닙니다", 사과가 아닙니다. apfel입니다. 기능적으로 여러분의 친구이며 여기에도 논리가 있습니다. 결국 중요한 것은 기능성이며, 그런 식으로 null을 사용하는 것은 기능성과 사용 편의성을 어느 정도 제공합니다. 더 유용합니까? ANSI 표준 때문에 이상한 방식으로 논리를 비교하여 논리를 끊임없이 깨뜨리고 있기 때문입니다. 컴퓨터 전원을 사용하여 우리를 위해 그것을하지 않는 이유는 무엇입니까? 관련된 모든 것이 그것을 염두에두고 구성되면 속도가 느려질 것입니다. "아무것도 null이 아닙니다", 사과가 아닙니다. apfel입니다. 기능적으로 여러분의 친구이며 여기에도 논리가 있습니다. 결국 중요한 것은 기능성이며, 그런 식으로 null을 사용하는 것은 기능성과 사용 편의성을 어느 정도 제공합니다. 더 유용합니까? 사과가 아닙니다. apfel입니다. 기능적으로 당신의 친구이며 여기에도 논리가 있습니다. 결국 중요한 것은 기능성이며, 그런 식으로 null을 사용하는 것은 기능성과 사용 편의성을 어느 정도 제공합니다. 더 유용합니까? 사과가 아닙니다. apfel입니다. 기능적으로 당신의 친구이며 여기에도 논리가 있습니다. 결국 중요한 것은 기능성이며, 그런 식으로 null을 사용하는 것은 기능성과 사용 편의성을 어느 정도 제공합니다. 더 유용합니까?

이 코드를 고려하십시오.

SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end

이 코드가 무엇을 반환하는지 아는 사람은 몇 명입니까? NOT 유무에 관계없이 0을 반환합니다. 나에게는 작동하지 않으며 혼란 스럽습니다. c #에서는 비교 연산이 값을 반환해야합니다. 논리적으로 이것도 값을 생성합니다. 왜냐하면 비교할 것이 없다면 (아무것도 제외 :). 그들은 단지 "보냈다": null "returns"0과 비교할 때 많은 해결 방법과 두통이 발생합니다.

이것은 나를 여기로 가져온 코드입니다.

where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)

두 필드 (어디에서)에 다른 값이 있는지 비교해야합니다. 함수를 사용할 수는 있지만 ...


4

NULL 비교 연산자를 사용하여 어떤 값과도 비교할 수 없습니다. NULL = NULL은 거짓입니다. 널은 값이 아닙니다. IS 연산자는 NULL 비교를 처리하도록 특별히 설계되었습니다.


5
때로는 임시 쿼리에서 사용할 수 null = null있는 곳을 사용할 때 혼란스러워하는 사람들을 항상 즐겼습니다 1=0. 그리고 그들이 불평하면, 나는 그것을 다음과 같이 변경합니다 null != null:)
SWeko

8
"NULL = NULL is false"그렇지 않습니다. NULL = NULL은 알 수없는 것으로 평가되고 거짓이 아닙니다.
nvogel

@ dportas는 그렇지만 조건부에서는 그것이 사실로 평가되지 않을 것을 의미했습니다.
Vincent Ramdhanie

@VincentRamdhanie는 거짓이 아닙니다. 실제로 postgres에서는 NULL로 평가됩니다
Pere

2

오래된 질문이지만 다음은 더 자세한 내용을 제공 할 수 있습니다.

null값이 없거나 알 수없는 값을 나타냅니다. 값이없는 이유를 지정하지 않으므로 모호성이 생길 수 있습니다.

다음과 같이 쿼리를 실행한다고 가정하십시오.

SELECT *
FROM orders
WHERE delivered=ordered;

즉, 날짜 ordereddelivered날짜가 동일한 행을 찾고 있습니다.

하나 또는 두 개의 열이 모두 null 일 때 예상되는 것은 무엇입니까?

날짜 중 적어도 하나를 알 수 없으므로 두 날짜가 같다고 말할 수는 없습니다. 날짜를 모두 알 수없는 경우에도 마찬가지입니다. 날짜가 무엇인지 모르는 경우 어떻게 동일 할 수 있습니까?

null따라서 값으로 취급 되는 모든 표현식 은 실패해야합니다. 이 경우 일치하지 않습니다. 다음을 시도하는 경우에도 마찬가지입니다.

SELECT *
FROM orders
WHERE delivered<>ordered;

다시 말하지만, 우리는 어떻게이 개 값은 말할 수 없습니다 우리는 그들이 무엇인지 모르는 경우 동일.

SQL에는 결 측값에 대한 특정 테스트가 있습니다.

IS NULL

특히 값을 비교하는 것이 아니라 누락 된 값을 찾습니다 .

마지막으로, !=운영자에 관해서는 , 내가 아는 한 실제로 표준에 있지는 않지만 매우 광범위하게 지원됩니다. 일부 언어의 프로그래머가 집에서 더 느끼도록하기 위해 추가되었습니다. 솔직히 프로그래머가 사용하는 언어를 기억하기 어려운 경우 나쁜 시작을합니다.


이것은 @Hove가 그의 답변에서 설명하는 것과 같은 "무의미한" "논리적"입니다. 진실은 이런 맥락에서 그 여분의 도구를 사용할 필요가 없다는 것입니다. 쉽게 우리가 뭔가를 비교하는 경우라고 가정 할 수 NULL우리 '가있는에 값을 비교하는 것을 의미 NULL하지 기저의가 있다는 결정되지 않은 값 "에 값 값' NULL¿ 데를? 그러나 우리는 모르는 ", 분명히 우리는 알 수 없을 것입니다. 그것은 정말로 일을 쉽게 할 것입니다.
Pere

@Pere 나는 그것이 엄밀히“무의미한”것이라고 말하지 않을 것이며, 글쓰기 IS NULL가 글쓰기보다 훨씬 어렵다는 것을 확신하지 못한다 = NULL. 나는 후자를 특별한 경우로 취급하기보다는와 WHERE columnA = columnB동일한 해석을 한다면 더 일관성이 있다고 생각합니다 WHERE columnA = NULL. 값 NULL아님을 기억하십시오 . 이 언어 프로그래밍 입니다 테스트 합법적 variable == null때문입니다 null다른 의미를 가진다; 그것은 알려지지 않은 것을 나타내지 않고 의도적으로 값을 재설정합니다. SQL에서는 그렇지 않습니다.
Manngo

따옴표 (@Mangoo;) (및 "logic") 사이에 넣는 이유가 여기에 있습니다. 나에게 화 내지 마라. 나는 당신의 설명이 아니라 ANSI "추론"에 대해 이야기하고있었습니다. 최신 예제에서 IS NULLAND 사이에 오버 헤드가 없다는 데 동의합니다 =NULL. 그러나 호버의 마지막 것을 살펴보십시오. 나는 그것을 반복해서 경험하는 데 지쳤다. 불필요한 짐을 많이해야합니까? 추가 점검 ...
Pere

1

값에 변화가 있는지 i, 새로운 가치가 있고 d, 오래된 것이지 (이 순서는 중요하지 않음) 찾을 수 있도록이 코드를 제안하고 싶습니다 . 그 점에서 값에서 널로 또는 그 반대로의 변경은 변경이지만 널에서 널로의 변경은 아닙니다 (물론, 값에서 다른 값으로의 변경은 값이지만 같은 값으로의 변경은 아닙니다).

CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
    @i sql_variant,
    @d sql_variant
)
RETURNS bit
AS
BEGIN
    DECLARE @in bit = 0, @dn bit = 0
    if @i is null set @in = 1
    if @d is null set @dn = 1

    if @in <> @dn
        return 0

    if @in = 1 and @dn = 1
        return 1

    if @in = 0 and @dn = 0 and @i = @d
        return 1

    return 0

END

이 기능을 사용하려면

declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)

---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp

---- where equal ----
select *,'equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 1

---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 0

결과는 다음과 같습니다.

---- in select ----
a   b   =
1   1   1
1   2   0
1   NULL    0
NULL    1   0
NULL    NULL    1

---- where equal ----
1   1   equal
NULL    NULL    equal

---- where not equal ----
1   2   not equal
1   NULL    not equal
NULL    1   not equal

sql_variant를 사용하면 다양한 유형에 호환됩니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.