4P by neo 8일전 | ★ favorite | 댓글 2개
  • SQL에서 NULL 값은 독특하게 처리됨. UNIQUE 제약 조건이 있는 열은 여러 NULL 값을 가질 수 있음.

    • 이는 각 NULL 값이 다른 NULL과 다른 독립적인 값으로 간주되기 때문임
    • SQLite, Postgres, MySQL 모두 동일하게 동작함.
  • 기준 설정

    select '' = '';    -- Returns 1 (true) 빈 문자열은 같음   
    select 1 = 1;      -- Returns 1 (true) 숫자는 같음   
    select 1 = 0;      -- Returns 0 (false) 숫자가 다름   
    select null = null; -- Returns NULL (null) 응?  
    
    • NULL은 "알려지지 않은 값"을 나타내는 자리 표시자이기 때문에, 두 개의 미지의 값이 동일하지 않다고 간주되기 때문임
    • IS 연산자를 사용하면 NULL의 정체성을 확인할 수 있음. 예를 들어, null is null은 TRUE를 반환함.
  • 고유성에 대해

    • UNIQUE 제약 조건이 있는 열에 NULL 값이 포함된 경우, NULL 값은 서로 다른 것으로 간주되어 고유성 제약 조건을 위반하지 않음.
    • 예를 들어, ('ray@mail.com', NULL)('ray@mail.com', NULL)은 서로 다른 행으로 간주됨.
  • NULL이 이렇게 처리되는 이유

    • SQLite 및 다른 SQL 호환 데이터베이스는 NULL을 다른 데이터베이스와 일관되게 처리하기 위해 이렇게 구현됨. SQL 표준 문서는 NULL이 모든 곳에서 고유해야 한다고 제안하지만, 실제로는 대부분의 SQL 엔진이 SELECT DISTINCT나 UNION에서 NULL을 고유하게 처리하지 않음.
  • 고유성을 보장하는 방법

    • 생성된 열 사용

      • NULL이 아닌 결정론적 값을 항상 가지는 열을 생성하여 문제를 완화할 수 있음. 예를 들어, COALESCE(deleted_at, '1970-01-01')를 사용하여 NULL 값을 대체할 수 있음.
      • 이 방법은 테이블에 추가 필드를 추가하여 공간을 차지할 수 있음.
    • 부분 인덱스 사용

      • deleted_at이 NULL인 경우에만 email에 대한 부분 인덱스를 생성하여 고유성을 보장할 수 있음.
      • 부분 인덱스는 테이블을 넓히지 않고 공간을 덜 차지하며, 동일한 레코드 쌍을 반복적으로 삭제할 때 오류가 발생하지 않음.
  • 업데이트

    • Oracle은 빈 문자열을 NULL로 처리함.
  • 결론

    • ORM을 사용할 때는 보이지 않지만, SQL NULL의 독특한 처리 방식은 혼란을 초래할 수 있음. SQL 표준 문서는 공개적으로 제공되지 않으며, 비용을 지불해야만 구할 수 있음.

모든 null은 이상하죠.
그래서 멀쩡한 SQL의 null이 오히려 이상한것 처럼 보이는…
애꾸눈 나라에선 두눈박이가 비정상…

Hacker News 의견
  • SQL의 NULL은 Kleene의 TRUE-FALSE-UNKNOWN 논리에 기반을 두고 있음. NULL을 UNKNOWN으로 읽으면 여러 연산이 더 직관적으로 이해됨

    • TRUE OR UNKNOWN = TRUE, TRUE AND UNKNOWN = UNKNOWN, UNKNOWN XOR UNKNOWN = UNKNOWN 등
    • NULL은 UNKNOWN을 나타내는 자리 표시자이며, 두 NULL이 같다고 할 수 없음
    • Postgresql 15부터는 NULLS NOT DISTINCT를 사용하여 고유 인덱스를 생성할 수 있음
  • 1970년대에 NULL 개념이 도입되었을 때, 미래에 많은 혼란을 초래할 것이라고 생각했음. 45년이 지난 지금도 여전히 논의 중임

  • NULL의 직관적인 이해: 특정 테이블 셀의 NULL 값은 '값 없음'을 나타내는 방법임. 고유한 값을 원할 때, 값이 없는 경우는 고려하지 않아야 함

  • ORM 사용에 대한 회의론: ORM은 편리하지만, 관계형 데이터베이스의 실제 작동 방식을 배우지 못한 세대가 생겨났음. SQL NULL의 동작은 기본 관계 대수와 일치하며, C 스타일의 NULL이 문제임

  • Blackadder 에피소드의 대화에서 NULL 비교의 유머를 상기함

  • Oracle에서 NULL이 빈 문자열과 같다는 점이 이상하다고 생각함

  • 객체 지향 컨텍스트에서 "null"은 특정 속성에 값이 없음을 나타내는 데 유용함. JavaScript에서는 null과 undefined가 있어, undefined는 값을 모르는 것이고 null은 값이 없음을 의미한다고 가정할 수 있음

  • NULL은 중복이 없다는 의미에서 이상하지 않음. NULL이 서로 같지 않기 때문에 중복이 될 수 없음. NULL 의미론이 마음에 들지 않으면 센티널 값을 사용할 수 있음

  • SQL NULL은 존재하지 않는 값이 있는 레코드에서 관계형 논리가 어떻게 작동하기를 원하는지를 고려하면 이상하지 않음