🚨 가장 중요한 핵심: IS NULL vs = NULL
❌ 절대 하면 안 되는 것
-- 🚫 틀렸습니다! 결과가 나오지 않습니다!
SELECT * FROM users;
-- INSERT 시에도 ISNULL 활용
INSERT INTO users (name, email, age, phone)
SELECT
N'새사용자',
ISNULL(@input_email, 'default@company.com'),
ISNULL(@input_age, 20),
ISNULL(@input_phone, '000-0000-0000');
2. COALESCE - 여러 값 중 첫 번째 유효값
-- COALESCE(값1, 값2, 값3, ...) - 첫 번째 NULL이 아닌 값 반환
SELECT
name,
COALESCE(email, phone, name + '@company.com', '연락처없음') AS contact_info
FROM users;
-- 여러 컬럼에서 값 찾기
SELECT
name,
COALESCE(phone, email, '연락불가') AS primary_contact
FROM users;
3. NULLIF - 특정 값을 NULL로 변환
-- NULLIF(값1, 값2) - 값1과 값2가 같으면 NULL, 다르면 값1 반환
SELECT
name,
NULLIF(email, '') AS clean_email, -- 빈 문자열을 NULL로
NULLIF(age, 0) AS valid_age, -- 0을 NULL로
NULLIF(phone, '000-0000-0000') AS real_phone -- 기본값을 NULL로
FROM users;
-- UPDATE에서 활용
UPDATE users
SET
email = NULLIF(email, ''),
phone = NULLIF(phone, '000-0000-0000')
WHERE id > 0;
실전 예제: 사용자 데이터 정리
1. 데이터 정리 쿼리
-- 더미 데이터가 포함된 사용자 테이블
CREATE TABLE messy_users (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(50),
email VARCHAR(100),
age INT,
phone VARCHAR(20),
status VARCHAR(20)
);
-- 지저분한 테스트 데이터 입력
INSERT INTO messy_users (name, email, age, phone, status) VALUES
(N'홍길동', 'hong@test.com', 25, '010-1234-5678', 'active'),
(N'김철수', '', 0, '', 'inactive'),
(N'이영희', NULL, -1, '000-0000-0000', ''),
(NULL, 'park@test.com', 30, NULL, 'active'),
(N'', 'empty@test.com', NULL, ' ', 'deleted');
-- ✅ 데이터 정리 작업
UPDATE messy_users
SET
-- 이름 정리: NULL이나 빈 문자열을 '알 수 없음'으로
name = CASE
WHEN name IS NULL OR LTRIM(RTRIM(name)) = '' THEN N'알 수 없음'
ELSE LTRIM(RTRIM(name))
END,
-- 이메일 정리: 빈 문자열을 NULL로
email = NULLIF(LTRIM(RTRIM(email)), ''),
-- 나이 정리: 0이나 음수를 NULL로
age = CASE
WHEN age <= 0 THEN NULL
ELSE age
END,
-- 전화번호 정리: 빈 문자열이나 기본값을 NULL로
phone = CASE
WHEN LTRIM(RTRIM(phone)) IN ('', '000-0000-0000') THEN NULL
ELSE LTRIM(RTRIM(phone))
END,
-- 상태 정리: 빈 문자열을 'unknown'으로
status = CASE
WHEN status IS NULL OR LTRIM(RTRIM(status)) = '' THEN 'unknown'
ELSE LTRIM(RTRIM(status))
END;
-- 정리 결과 확인
SELECT * FROM messy_users;
2. 조건부 삽입 (UPSERT 패턴)
-- 존재하지 않으면 INSERT, 존재하면 UPDATE
MERGE users AS target
USING (
SELECT
N'새사용자' AS name,
'new@test.com' AS email,
25 AS age,
'010-5555-6666' AS phone
) AS source ON target.email = source.email
WHEN MATCHED THEN
UPDATE SET
name = ISNULL(source.name, target.name),
age = ISNULL(source.age, target.age),
phone = ISNULL(source.phone, target.phone)
WHEN NOT MATCHED THEN
INSERT (name, email, age, phone)
VALUES (source.name, source.email, source.age, source.phone);
자주하는 실수와 해결방법
1. 문자열 연결 시 NULL 문제
-- ❌ 문제: NULL과 문자열을 연결하면 결과가 NULL
SELECT name + ' (' + email + ')' AS display_name FROM users;
-- 결과: email이 NULL이면 전체가 NULL
-- ✅ 해결방법 1: ISNULL 사용
SELECT name + ' (' + ISNULL(email, '이메일없음') + ')' AS display_name
FROM users;
-- ✅ 해결방법 2: CONCAT 함수 사용 (NULL을 빈 문자열로 처리)
SELECT CONCAT(name, ' (', email, ')') AS display_name
FROM users;
2. 숫자 계산 시 NULL 문제
-- ❌ 문제: NULL과 계산하면 결과가 NULL
SELECT age + 10 AS age_plus_10 FROM users;
-- 결과: age가 NULL이면 NULL + 10 = NULL
-- ✅ 해결방법: ISNULL로 기본값 설정
SELECT ISNULL(age, 0) + 10 AS age_plus_10 FROM users;
-- ✅ 평균 계산시 NULL 제외
SELECT
AVG(age) AS avg_age, -- NULL 자동 제외
AVG(ISNULL(age, 0)) AS avg_age_with_zero -- NULL을 0으로 처리
FROM users;
3. WHERE 절에서의 NULL 처리
-- ❌ 문제: 예상과 다른 결과
SELECT * FROM users WHERE age <> 25; -- age가 NULL인 행은 결과에 없음!
-- ✅ 해결방법: NULL도 포함하려면
SELECT * FROM users WHERE age <> 25 OR age IS NULL;
-- ✅ 또는 ISNULL 사용
SELECT * FROM users WHERE ISNULL(age, -1) <> 25;
실무에서 자주 사용하는 패턴
1. 사용자 입력 데이터 처리
-- 웹폼에서 받은 데이터 처리 (빈 문자열을 NULL로)
DECLARE @input_name NVARCHAR(50) = N'홍길동';
DECLARE @input_email VARCHAR(100) = ''; -- 빈 문자열
DECLARE @input_age VARCHAR(10) = ''; -- 빈 문자열
DECLARE @input_phone VARCHAR(20) = NULL;
INSERT INTO users (name, email, age, phone)
VALUES (
NULLIF(LTRIM(RTRIM(@input_name)), ''),
NULLIF(LTRIM(RTRIM(@input_email)), ''),
CASE
WHEN @input_age = '' OR @input_age IS NULL THEN NULL
ELSE CAST(@input_age AS INT)
END,
NULLIF(LTRIM(RTRIM(@input_phone)), '')
);
2. 검색 쿼리 (NULL 값도 고려)
-- 전체 사용자 검색 (NULL 값도 검색 결과에 포함)
SELECT
name,
ISNULL(email, '이메일 없음') AS email_display,
CASE
WHEN age IS NULL THEN '나이 미입력'
ELSE CAST(age AS NVARCHAR(10)) + '세'
END AS age_display,
ISNULL(phone, '전화번호 없음') AS phone_display
FROM users
WHERE
(name LIKE N'%홍%' OR name IS NULL) -- 이름에 '홍'이 포함되거나 NULL
AND (age >= 20 OR age IS NULL); -- 20세 이상이거나 나이 미입력
-- 동적 검색 (검색조건이 NULL이면 모든 값 포함)
DECLARE @search_name NVARCHAR(50) = NULL; -- 검색조건
DECLARE @search_min_age INT = 20;
SELECT * FROM users
WHERE
(@search_name IS NULL OR name LIKE N'%' + @search_name + N'%')
AND (@search_min_age IS NULL OR age >= @search_min_age OR age IS NULL);
3. 데이터 유효성 검사
-- 필수 필드 검사
SELECT
id,
name,
email,
CASE
WHEN name IS NULL OR LTRIM(RTRIM(name)) = '' THEN '이름 필수'
WHEN email IS NULL OR LTRIM(RTRIM(email)) = '' THEN '이메일 필수'
WHEN email NOT LIKE '%@%' THEN '이메일 형식 오류'
ELSE 'OK'
END AS validation_result
FROM users
WHERE name IS NULL
OR LTRIM(RTRIM(name)) = ''
OR email IS NULL
OR LTRIM(RTRIM(email)) = ''
OR email NOT LIKE '%@%';
요약: NULL 처리 체크리스트
✅ 꼭 기억해야 할 것들
- 조건문에서는 IS NULL / IS NOT NULL 사용
- WHERE column IS NULL -- ✅ 맞음 WHERE column = NULL -- ❌ 틀림
- ISNULL 함수로 NULL 대체값 지정
- SELECT ISNULL(column, '기본값') FROM table;
- INSERT/UPDATE 시 빈 문자열과 NULL 구분
- INSERT INTO table VALUES (NULL); -- NULL 입력 INSERT INTO table VALUES (''); -- 빈 문자열 입력
- 문자열 연결 시 NULL 처리
- SELECT CONCAT(col1, col2); -- NULL을 빈 문자열로 처리 SELECT col1 + ISNULL(col2, ''); -- 또는 ISNULL 사용
- 동적 검색 시 NULL 조건 포함
- WHERE (@param IS NULL OR column = @param)
이 가이드를 따라하면 MSSQL에서 NULL 처리로 인한 대부분의 문제를 해결할 수 있습니다! WHERE age = NULL; UPDATE users SET name = '홍길동' WHERE age = NULL; DELETE FROM users WHERE phone = NULL;
### ✅ 올바른 방법
```sql
-- ✅ 맞습니다! 이렇게 해야 합니다!
SELECT * FROM users WHERE age IS NULL;
UPDATE users SET name = '홍길동' WHERE age IS NULL;
DELETE FROM users WHERE phone IS NULL;
-- NOT NULL 체크도 마찬가지
SELECT * FROM users WHERE age IS NOT NULL;
NULL이란 무엇인가?
NULL은 "값이 없음" 또는 "알 수 없음"을 의미합니다.
- 빈 문자열 ''과는 다릅니다
- 숫자 0과도 다릅니다
- 공백 ' '과도 다릅니다
-- NULL과 다른 값들의 차이점 보기
CREATE TABLE null_test (
id INT IDENTITY(1,1),
text_col VARCHAR(50),
number_col INT
);
INSERT INTO null_test VALUES
('안녕하세요', 100), -- 일반 값
('', 0), -- 빈 문자열, 0
(' ', NULL), -- 공백, NULL
(NULL, NULL); -- 모두 NULL
-- 결과 확인
SELECT
id,
text_col,
number_col,
CASE
WHEN text_col IS NULL THEN 'NULL값'
WHEN text_col = '' THEN '빈문자열'
WHEN text_col = ' ' THEN '공백'
ELSE '일반값'
END AS text_status
FROM null_test;
INSERT 시 NULL 처리
1. 기본 INSERT 방법
-- 테스트 테이블 생성
CREATE TABLE users (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(50) NOT NULL, -- NULL 불허
email VARCHAR(100), -- NULL 허용
age INT, -- NULL 허용
phone VARCHAR(20), -- NULL 허용
created_at DATETIME2 DEFAULT GETDATE()
);
-- ✅ 올바른 INSERT 방법들
-- 방법 1: 명시적으로 NULL 지정
INSERT INTO users (name, email, age, phone)
VALUES (N'홍길동', 'hong@email.com', 25, NULL);
-- 방법 2: 컬럼을 아예 생략 (자동으로 NULL 또는 DEFAULT)
INSERT INTO users (name, email)
VALUES (N'김철수', 'kim@email.com');
-- 방법 3: 여러 행 동시 입력
INSERT INTO users (name, email, age, phone) VALUES
(N'이영희', 'lee@email.com', 30, '010-1234-5678'),
(N'박민수', NULL, 28, '010-9876-5432'),
(N'최은정', 'choi@email.com', NULL, NULL);
2. INSERT 시 주의사항
-- ❌ 이렇게 하면 오류 발생
INSERT INTO users (name, email, age, phone)
VALUES (NULL, 'test@email.com', 25, '010-1111-2222');
-- 오류: name 컬럼은 NOT NULL 제약조건 위반
-- ❌ 빈 문자열과 NULL 혼동 주의
INSERT INTO users (name, email, age, phone)
VALUES (N'테스트', '', 25, ''); -- email과 phone에 빈 문자열 입력 (NULL 아님!)
-- ✅ NULL을 의도했다면 명시적으로
INSERT INTO users (name, email, age, phone)
VALUES (N'테스트', NULL, 25, NULL);
UPDATE 시 NULL 처리
1. NULL 값을 업데이트하기
-- ✅ NULL 값들을 업데이트
-- 나이가 NULL인 사용자들의 나이를 0으로 변경
UPDATE users
SET age = 0
WHERE age IS NULL;
-- 이메일이 NULL인 사용자들에게 기본 이메일 설정
UPDATE users
SET email = name + '@company.com'
WHERE email IS NULL;
-- 전화번호가 NULL인 사용자들에게 기본값 설정
UPDATE users
SET phone = '000-0000-0000'
WHERE phone IS NULL;
2. 값을 NULL로 업데이트하기
-- ✅ 기존 값을 NULL로 변경
-- 특정 사용자의 전화번호 삭제 (NULL로 변경)
UPDATE users
SET phone = NULL
WHERE id = 1;
-- 이메일 주소가 잘못된 사용자들의 이메일을 NULL로 변경
UPDATE users
SET email = NULL
WHERE email NOT LIKE '%@%';
-- 나이가 0인 사용자들의 나이를 NULL로 변경
UPDATE users
SET age = NULL
WHERE age = 0;
3. 조건부 UPDATE
-- ✅ CASE문을 사용한 조건부 UPDATE
UPDATE users
SET
email = CASE
WHEN email IS NULL THEN name + '@default.com'
WHEN email = '' THEN name + '@default.com'
ELSE email
END,
age = CASE
WHEN age IS NULL THEN 0
WHEN age < 0 THEN 0
ELSE age
END
WHERE id > 0;
-- ✅ ISNULL 함수 사용
UPDATE users
SET phone = ISNULL(phone, '000-0000-0000')
WHERE phone IS NULL;
-- ✅ COALESCE 함수 사용 (여러 값 중 첫 번째 NULL이 아닌 값)
UPDATE users
SET email = COALESCE(email, name + '@backup.com', 'unknown@company.com')
WHERE email IS NULL;
NULL 처리 유용한 함수들
1. ISNULL - 가장 많이 사용
-- ISNULL(값, 대체값) - 값이 NULL이면 대체값 반환
SELECT
name,
ISNULL(email, '이메일 없음') AS email_display,
ISNULL(age, 0) AS age_display,
ISNULL(phone, '전화번호 없음') AS phone_display
FROM users