개발 언어에서는 실수형 데이터를 float 타입으로 선언하곤 합니다. 이 때문에 DB를 구성할 때도 실수형 데이터가 저장될 열을 FLOAT 타입으로 선언하지요.
ALTER TABLE 테이블이름 ADD COLUMN 컬럼이름 FLOAT;
하지만, 실제로 데이터를 저장한 다음 평균을 내거나 합계를 내보면 조금씩 차이가 나는 현상을 발견하게 됩니다.
이유는 바로 FLOAT 타입이 근사 값을 저장하기 때문입니다. (FLOAT, REAL, DOUBLE PRECISION 모두 동일합니다.)
이는 msdn에서도 다음과 같이 명확히 설명하고 있습니다.
부동 소수점 데이터는 근사 값이므로 해당 데이터 형식 범위에 있는 모든 값을 정확하게 표현할 수는 없습니다.
– 출처 : msdn
조금 헷갈리시겠지만, 실수(float)형 데이터를 DB에 저장할 때는 해당 열을 FLOAT 타입이 아닌 NUMERIC이나 DECIMAL 형으로 선언해야 합니다. (Oracle에서는 BINARY_FLOAT에서 문제가 생깁니다. 그냥 FLOAT은 괜찮답니다.)
이런 식으로 개발자가 SQL을 작성할 때, 너무나 일반적으로 사용하고 있지만(Pattern) 자세히 들춰보면 옳지 않은 방법을 SQL AntiPattern(안티패턴)이라고 합니다.
이번에 저희가 출간한 SQL AntiPatterns에는 이런 예들이 무려 25가지나 소개됩니다.
재미있는 안티패턴을 또 하나 소개하자면… 바로 NULL 설정과 관련된 예입니다.
사용자 테이블에서 email 열에 NULL 값이 허용되었을 때, email을 입력하지 않은 사용자를 찾기 위해서는 보통 다음과 같은 SQL을 머릿속에 떠올릴 것입니다.
SELECT * FROM 테이블이름 WHERE email = NULL;
하지만 이 SQL문의 결과는 없습니다(NULL). NULL과는 어떤 값을 비교해도 결과가 False이기 때문이죠. 무슨 말이냐고요? 다음과 같은 예를 들어 보죠. (저자가 책에서 설명한 예를 조금 각색했습니다. ^^)
윤아의 나이가 22세이고, 효연의 나이를 모른다고 할 때, ‘윤아가 효연이보다 나이가 많아?’라는 질문에 대한 답은 ‘모른다’입니다. 반대도 마찬가지고요. 둘의 나이가 같으냐고 물어도 역시 ‘모른다’고 대답할 수밖에 없죠.
서현이의 나이도 모른다고 해보죠. 서현이와 효연이의 나이가 같은지 물어본다면 역시나 ‘모른다’고 말할 수밖에 없습니다. 이것이 바로 NULL = NULL의 결과가 False인 이유입니다.
(얼마 전 소녀시대가 프랑스에서 날렸다기에 적어본 것 뿐입니다. 절대로. 그 이유 뿐이예요.)
그렇다면, email 열에 어떤 값이라도 들어있는, 즉 NULL이 아닌 사용자를 찾기 위해 다음처럼 SQL을 만드는 건 어떨까요?
SELECT * FROM 테이블이름 WHERE NOT (email = NULL); 혹은 SELECT * FROM 테이블이름 WHERE email <> NULL;
역시나 결과는 NULL입니다. 서현이와 효연이의 나이가 같은지 물어봤을 때 ‘모른다’고 대답했듯이, 둘의 나이가 다르냐고 물어봐도 역시나 ‘모른다’고 대답할 밖에요.
자… 여기까지 보셨으면 다른 안티패턴들은 어떤 내용인지 궁금하실텐데요~. (궁금하셔야만 하는 겁니다. ㅎㅎ)
남들이 하는 대로 SQL을 사용하기보다, 올바른 방식으로 SQL을 사용하려는 모든 개발자들께서는 지금 온라인 서점으로 달려가시면 되겠습니다. ^^
이야 그런것도 있었군요. 전 DB를 사용하질 않아서 몰랐는데 말이죠 ^^ 우리 웹팀에게 추천해야겠습니다. 좋아라하겠네요~
좋아요좋아요