by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

14장. 모르는 것에 대한 두려움




14장. 모르는 것에 대한 두려움

14.1 목표: 누락된 값을 구분하기

  • 테이블과 쿼리에서 NULL 값을 생산적으로 사용할 수 있는 다양한 방법이 있다.
    • 여전히 일하고 있는 직원의 퇴사일과 같이, 행을 생성할 때 값을 알 수 없는 곳에 NULL을 사용할 수 있다.
    • 전기만 사용하는 자동차에 대한 연료 효율과 같이, 주어진 칼럼이 주어진 행에서 적용 가능한 값이 없는 경우에 NULL값을 사용할 수 있다.
    • 함수에 인수로 DAY('2009-12-32')와 같이 유효하지 않은 값이 입력되는 경우 NULL을 리턴할 수 있다.
    • 외부 조인에서 매치되지 않는 행의 칼럼 값의 자리를 채우는 데 NULL 값을 사용한다.

14.2 안티패턴: NULL을 일반 값처럼 사용

  • SQL에서는 NULL을 0이나 false 또는 빈 문자열과 다른 특별한 값으로 취급한다.
    (Oracle이나 Sybase에서는 NULL이 길이가 0인 문자열과 동일 - NULL을 문자열 데이터로 취급할때)

수식에서 NULL 사용

  • NULL은 0과 같지 않다. NULL + 10 = NULL
  • 표준 SQL에서는 어떤 문자열도 NULL과 연결하면 NULL (Oracle, Sybase 예외)
  • NULL은 false와도 같지 않다.
  • NULL이 들어간 불리언 수식은 AND, OR, NOT을 사용하더라도 항상 NULL

NULL을 가질 수 있는 컬럼 검색

SELECT * FROM Bugs WHERE assigned_to = 123;

SELECT * FROM Bugs WHERE NOT (assigned_to = 123);
  • 두 쿼리 모두 assigned_to 컬럼의 값이 NULL인 행은 리턴하지 않는다.
SELECT * FROM Bugs WHERE assigned_to = NULL;

SELECT * FROM Bugs WHERE assigned_to <> NULL;
  • NULL과의 비교는 그냥 NULL.
  • 두 쿼리 모두 assigned_to 컬럼의 값이 NULL인 행을 리턴하지 않는다.

쿼리 파라미터로 NULL 사용

SELECT * FROM Bugs WHERE assigned_to = ?;

파라미터를 받는 SQL에서는 NULL을 다른 일반적인 값처럼 사용하기 어렵다. NULL을 파라미터로 사용할 수 없다.

문제 회피하기

  • NOT NULL로 선언 후 의미 없는 기본값 부여.
  • 숫자 컬럼의 경우 SUM()이나 AVG() 같은 계산시 값이 포함 된다.

14.3 안티패턴 인식 방법

  • "assigned_to 칼럼에 아무 값도 설정되지 않은 행을 어떻게 찾을 수 있지?"
  • "애플리케이션에서 몇몇 사용자의 전체 이름이 표시되지 않아. 데이터베이스에서는 분명 볼 수 있는데."
  • "이 프로젝트의 전체 작업시간 보고서에 우리가 완료한 몇몇 버그만 포함되어 있어! 그러니까 우선순위를 할당한 것들만 포함이 되어 있네"
  • "Bugs 테이블에서 '알 수 없음'을 나타내는 데 예전에 사용하던 문자열을 사용할 수 없다는 것을 확인했기 때문에,
    다른 어떤 값을 사용해야 할 지 그리고 데이터를 변환해서 우리 코드가 새로운 값을 사용하도록 하는데 개발 기간이 얼마나 필요할지 논의하기 이한 회의가 필요해."

14.4 안티패턴 사용이 합당한 경우

  • NULL을 사용하는 것은 안티패턴이 아니다. NULL을 일반적인 값처럼 사용하거나 일반적인 값을 NULL처럼 사용하는 것이 안티패턴이다.

14.5 해법: 유일한 값으로 NULL을 사용하라

스칼라 수식에서의 NULL

불리언 수식에서의 NULL

NULL 검색하기

SELECT * FROM Bugs WHERE assigned_to IS NULL;

SELECT * FROM Bugs WHERE assigned_to IS NOT NULL;
  • SQL-99 표준에서는 IS DISTINCT FROM 이란 비교연산자가 정의됨. <> 과 비슷하게 동작. 피연산자가 NULL이더라도 항상 ture 또는 false를 리턴.
    SELECT * FROM Bugs WHERE assigned_to  IS NULL OR assigned_to <> 1;
    
    SELECT * FROM Bugs WHERE assigned_to IS DISTINCT FROM 1;
    

code:sql}
SELECT * FROM Bugs WHERE assigned_to IS DISTINCT FROM ?;


  • 쿼리 파라미터로 리터럴 값이나 NULL을 보내고 싶을 때 이 연사자 사용.
  • PostgreSQL, IBM DB2, Firebird 지원, Oracle과 Microsoft SQL Server는 미 지원. MySQL은 전용 연산자 <=> 제공.

컬럼을 NOT NULL로 선언하기

  • NULL 값이 애플리케이션 정책을 위반하거나 또는 의미가 없는 경우에는 컬럼에 NOT NULL 제약조건을 선언하라.
  • 필요에 따라서는 DEFAULT 값을 정의해라.

동적 디폴트

  • 주어진 컬럼이나 수식에, 특히 특정 쿼리에서만 디폴트 값을 설정하는 방법이다. coalesce() 함수 사용.
    (NVL() 혹은 ISNULL() 함수 사용)

어떤 데이터 타입에 대해서든 누락된 값을 뜻하는데는 NULL을 사용하라.

문서에 대하여

  • 최초작성일 : 2011년 12월 10일
  • 이 문서는 오라클클럽 코어 오라클 데이터베이스 스터디 모임에서 작성하였습니다.
  • 이 문서의 내용은 인사이트(insight) 에서 출간한 'SQL AntiPatterns : 개발자가 알아야 할 25가지 SQL 함정과 해법'를 참고하였습니다.

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.