T-SQL CASE 절 : WHEN NULL을 지정하는 방법


227

나는 이와 비슷한 T-SQL 문을 썼다 (원래는 다르게 보였지만 여기에 쉬운 예를주고 싶다) :

SELECT first_name + 
    CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person

이 문장에는 구문 오류가 없지만 case-clause는 항상 last_name이 null 인 경우에도 ELSE 부분을 선택합니다. 그런데 왜?

내가하고 싶은 것은 first_name과 last_name을 결합하는 것이지만 last_name이 null이면 전체 이름이 null이됩니다.

SELECT first_name +
   CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name 
FROM dbo.person

문제가 어디 있는지 아십니까?

답변:


369
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END

4
@ Luther의 COALESCE 제안은 내 대답보다 낫습니다. 조금 덜 효율적이지만 훨씬 더 우아합니다.
Marcelo Cantos

COALESCE (last_name, '') 대소 문자를 구분하면서 대소 문자를 구분할 수있는 경우는 큰 쿼리에서 COALESCE보다 유지 관리가 쉽지 않습니다. 결국 결과는 같습니다. 최적화 해야하는 경우 실행 계획을 확인하지만 큰 차이는 없습니다.
Anthony Mason

1
COALESCE기본적으로 내부적으로로 번역됩니다 CASE. CASE의 문제점 last_name은 두 번 평가되며 다른 부작용으로 이어질 수 있다는 것 입니다. 이 우수한 기사를 참조하십시오 . 요청 된 것을 해결하기 위해 아래 주석에ISNULL(' '+ last_name, '') 언급되어 있습니다.
miroxlav

41

WHEN 부분은 ==와 비교되지만 실제로 NULL과 비교할 수는 없습니다. 시험

CASE WHEN last_name is NULL  THEN ... ELSE .. END

대신 또는 COALESCE :

COALESCE(' '+last_name,'')

( 'last_name이 NULL 인 경우' '+ last_name은 NULL이므로이 경우' '를 반환해야합니다.)


WHEN 부분에 ==가 포함 된 정보에 대해 감사합니다. 나는 몰랐다. COALESCE를 사용하면 잘 작동합니다. 그렇게 할 가능성이 너무 많다고 생각하지 않았습니다.
meni

15

많은 해결책이 있지만 원래 진술이 효과가없는 이유는 다루지 않습니다.

CASE last_name WHEN null THEN '' ELSE ' '+last_name

그 후, 평등에 대한 점검이 있으며, 이는 참 또는 거짓이어야합니다.

비교의 하나 또는 두 부분이 모두 널인 경우, 비교 결과는 알 수 없음이며 케이스 구조에서 false로 처리됩니다. 참조 : https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

이를 피하기 위해 Coalesce가 최선의 방법입니다.


11

쿼리가 주어지면 다음과 같이 할 수도 있습니다.

SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person

2
이것은 last_name이 널일 때 중복 공간을 추가하여 OP가 피하려고 시도한 것입니다.
Marcelo Cantos

6
ISNULL(' '+ last_name, '')중복 공간을 방지하기 위해 더 나은 사용 .
Prutswonder

예, 게시 한 후에 깨달았습니다. 그가 문제를 겪고 있던 부분을 해결했기 때문에 나는 그것을 떠날 것이라고 생각했다.
이안 제이콥스

7

문제는 널 (null)이 자신과 동일하게 간주되지 않기 때문에 절이 일치하지 않는다는 것입니다.

널을 명시 적으로 확인해야합니다.

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name

5

시험:

SELECT first_name + ISNULL(' '+last_name, '') AS Name FROM dbo.person

이렇게하면성에 공백이 추가되고, 널 (null)이면 전체 space + 성은 NULL이되고 이름 만 얻습니다. 그렇지 않으면 firts + space + 성을 얻습니다.

null 문자열과의 연결에 대한 기본 설정이 설정되어 있으면 작동합니다.

SET CONCAT_NULL_YIELDS_NULL ON 

OFF이후 버전의 SQl Server에서는 모드가 사라 지기 때문에 걱정할 필요가 없습니다.


4

문제는 NULL이 자체와 다른 것으로 간주되지 않지만 이상한 부분은 자체와 동일 하지 않다는 것입니다.

다음 문장을 고려하십시오 (SQL Server T-SQL에서는 BTW가 불법이지만 My-SQL에서는 유효하지만 ANSI가 null을 정의하는 것이므로 SQL 문에서도 대소 문자를 사용하여 확인할 수 있습니다).

SELECT NULL = NULL -- Results in NULL

SELECT NULL <> NULL -- Results in NULL

따라서 질문에 대한 참 / 거짓 답변이 없으며 대신 답도 null입니다.

예를 들어

  1. 명시 적으로 사용하지 않는 경우에 null 값이 항상 ELSE 절을 사용하는 CASE 문은, 언제 NULL 조건 (IS NOT 조건 )WHEN NULL
  2. 문자열 연결
    SELECT a + NULL -- Results in NULL
  3. WHERE IN 또는 WHERE NOT IN 절에서, 올바른 결과를 원하는 것처럼 상관 부속 조회에서 널값을 필터링하도록하십시오.

을 지정하여 SQL Server에서이 동작을 무시할 수 SET ANSI_NULLS OFF있지만 그렇지 않습니다. 권장하고 많은 문제가 발생할 수해서는 안 단순히 때문에 표준 편차.

참고로 My-SQL에는 <=>null 비교를 위해 특수 연산자를 사용하는 옵션이 있습니다 .

비교해 보면, 일반 프로그래밍 언어에서 null 처리는 정규 값이며 자체와 동일하지만 NAN 값은 자체와 동일하지 않지만 적어도 자체와 비교할 때 'false'를 반환합니다. 다른 프로그래밍 언어가 다른 구현 언어를 가지고 있는지 확인하십시오).

그러나 기본 언어 (예 : VB 등)에는 'null'키워드가 없으며 대신 'Nothing'키워드를 사용합니다.이 키워드는 직접 비교에 사용할 수 없으며 대신 SQL에서 'IS'를 사용해야합니다. 그러나 실제로는 (간접 비교를 사용할 때) 자체와 같습니다.


1
"이상한 부분은 그것 자체와도 같지 않다는 것입니다." => SQL에서 null이 '알 수 없음'이라는 의미를 가지고 있다는 것을 고려하면 이상하지 않습니다. 알려지지 않은 것은 알려지지 않은 다른 것과 거의 같지 않습니다.
JDC

1
CASE  
    WHEN last_name IS null THEN '' 
    ELSE ' ' + last_name 
END

1

당신이 이것을 시도 좌절 얻을 때 :

CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END

대신 이것을 시도하십시오 :

CASE LEN(ISNULL(last_Name,''))
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

LEN(ISNULL(last_Name,''))이 열의 문자 수를 측정합니다. 비어 있거나 NULL인지 여부는 0이므로 WHEN 0 THENtrue로 평가되고 예상대로 ''를 반환합니다.

이것이 유용한 대안이기를 바랍니다.

SQL Server 2008 이상에 대한이 테스트 사례를 포함 시켰습니다.

DECLARE @last_Name varchar(50) = NULL

SELECT 
CASE LEN(ISNULL(@last_Name,''))
WHEN 0 THEN '' 
ELSE 'A ' + @last_name
END AS newlastName

SET @last_Name = 'LastName'

SELECT 
CASE LEN(ISNULL(@last_Name,''))
WHEN 0 THEN '' 
ELSE 'A ' + @last_name
END AS newlastName

2
확실하게 작동합니까? NULL 입력이 주어질 때 대부분의 함수는 NULL을 반환하고, 테스트 결과 LEN ()도 마찬가지임을 확인합니다. 즉, LEN (NULL)은 0이 아닌 NULL을 반환합니다.
Jason Musgrove

Pokechu22가 정확하고 다음과 같은 스크립트가 수정되었습니다. CASE LEN (ISNULL (last_Name, '')) 0시 다음 ''ELSE ''+ last_name END AS newlastName
Chef Slagle

0

Jason이 오류를 발견하여 작동합니다 ...

다른 플랫폼 버전을 확인할 수 있습니까?
SQL 서버 :

SELECT
CASE LEN(ISNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

MySQL :

SELECT
CASE LENGTH(IFNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

신탁:

SELECT
CASE LENGTH(NVL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

0

IsNull 기능을 사용할 수 있습니다

select 
    isnull(rtrim(ltrim([FirstName]))+' ','') +
    isnull(rtrim(ltrim([SecondName]))+' ','') +
    isnull(rtrim(ltrim([Surname]))+' ','') +
    isnull(rtrim(ltrim([SecondSurname])),'')
from TableDat

하나의 열이 null이면 빈 문자가 표시됩니다.

Microsoft SQL Server 2008+와 호환


0

SQL Server 2012부터 사용 가능한 CONCAT 기능을 사용하십시오.

SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE

0

문자열로 캐스팅하고 길이가 0 인 문자열을 테스트하려고 시도했지만 작동했습니다.

CASE 
   WHEN LEN(CAST(field_value AS VARCHAR(MAX))) = 0 THEN 
       DO THIS
END AS field 

0

NULL은 아무것도 아닙니다. case 문은 기본적으로 value = NULL 일 때 말하는 것입니다.
구문으로 잘못 작성된 여러 시스템 저장 프로시 저도 있습니다. sp_addpullsubscription_agent 및 sp_who2를 참조하십시오.
시스템 저장 프로 시저를 변경할 수 없기 때문에 이러한 실수를 Microsoft에 알리는 방법을 알고 싶습니다.

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