본문 바로가기

DB스토리/MYSQL

MYSQL SET 타입 관련

 

SET 이라는 자료형입니다. enum 과 유사하게 생겼으나 전혀 다른 별개의 자료형입니다.

enum ('a','b','c') 라고 정의된 필드가 있다고 생각합시다.

이 자료형은 a 나 b, c(혹은 null) 중 단 하나의 값을 가질수 있습니다.


set('a','b','c') 라고 정의된 필드는 enum과는 조금 다르게

null, a, b, c, (a,b), (a,c)... (a,b,c) 와 같은 값을 가질수 있습니다.

enum과는 달리 복수개의 아이템을 값으로 가질수가 있습니다.

그리고 또 하나 set 에 정의된 아이템은 비트 연산이 가능합니다.

null - 000 (0)
a     - 001 (1)
b     - 010 (2)
c     - 100 (4)
a,b  - 011 (3)
a,b,c - 111 (7)

set 형은 최대 64개의 아이템을 가질수 있고 select 문을 통해서 문자열 혹은 정수 값으로 열람이 가능합니다.

비트연산을 통해 비교구문을 활용할수 있고 그 응용범위는 넓습니다.


제 경우엔 수강신청 프로그램에 활용을 하였습니다.

각 과목은 월1~금15 까지 중 일부의 가변 갯수의 수업시간을 가집니다.

그리고 수강신청시 이미 신청한 과목과  중복된 과목은 신청할수 없겠죠?


원래는 정수형으로 필드를 설정해놓고 각 시간별로 비트를 하나씩 부여해서 php 에서 처리해주려고 했는데

이미 mysql 에 set형이라는 유사한 자료형이 있더라구요..

이 경우 기존에 수강신청한 자료에서 이미 신청한 과목의 시간을 모두 얻어

이 값을 or 연산을 해주고, 그 값과 현재 신청하려는 수강과목의 시간을 and 해주어서

그 결과가 0이 나와야 신청이 가능하겠죠??


많은 도움이 되셨나요?

SET 타입의 장점으로는
그 리스트를 bit 형 숫자 또는 문자열 모두 또는 이들 두개의 조합으로도
가능하기 때문에 잘 구성하면 테이블에서 직접 눈으로 쉽게 판별할수도 있습니다.

예를들어, 위의 경우라면,

colanme SET('1','2','3','4','5',...) DEFAULT ...
또는
colanme SET('1','2','4','8','16',...) DEFAULT ...       <---- bit
또는
colanme SET('1st','2st','3st','4st','5st',...) DEFAULT ...
또는
colanme SET('a','b','c','d','e',...) DEFAULT ...
...

등등 여러가지 형태로 가능하고 실제로 이들은 내부적으로
모두 두번째 예인 비트단위로 DB 에 저장됩니다.

4번째의 경우라면

a => 1
b => 2
c => 4
d => 8
e => 16

이와같이 내부는 실제의 문자나 문자열로 연산하지 않고 오른쪽의 비트단위인 숫자로
증가하면서 저장되고 숫자형으로 비교하기 때문에 상당히 빠른다는 장점이
있습니다.

참고로, ENUM 은 1씩 증가하고 택일이지만, SET 타입은 비트 단위로 증가하고
다중선택이 가능합니다. 물론 크기는 ENUM 이 더 작습니다.

SET 타입의 자료입력은

예)
INSET INTO SET ... colname = 'a';
INSET INTO SET ... colname = 'a,b';
INSET INTO SET ... colname = 'b,a'; // 순서가 바뀌면 a,b 순서로 자동으로 저장
INSET INTO SET ... colname = 'd,e';
INSET INTO SET ... colname = 'b,c,d';

이와 같은 형식으로 자료를 입력하면 됩니다.

이들을 각각

'a'     => 1
'a,b'   => 1 + 2 = 3
'd,e'   => 8 + 16 = 24
'b,c,d' => 2 + 4 + 8 = 14

이렇게 내부적인 비트단위로 저장되고 연산됩니다.
출력은 비트단위의 숫자가 아닌 원래의 저정한 형태의 자료형으로
출력됩니다.

검색부분에 대해서도 숫자형 BIGINT 와 같이 숫자형 연산도
가능할 뿐더러 문자열 비교도 할 수 있습니다.

BININT 같은 경우도 LIKE 와 같은 문자열 비교 연산도 가능하지만
잘못된 결과가 나올 수 있기 때문에 역시 곤란합니다.
반면 SET 타입은 문자열로도 취급가능하므로 LIKE 에 대한 잘못된
결과가 나오는 경우는 없습니다.

굳지 예를 들자면(문자형태로 저장되었을 경우),

1) 문자열로 취급할 경우

SELECT ... WHERE colname = 'a,b'; // a 와 b 만 선택한 경우
SELECT ... WHERE colname LIKE 'a%'; // 최소한 a 를 선택한 경우
SELECT ... WHERE colname IN('a','b'); // a 또는 b 만 선택한 경우
SELECT ... WHERE FIND_IN_SET('a',colname); // 최소한 a 를 선택한 경우
SELECT ... WHERE INSTR(colname,'a'); // 최소한 a 를 선택한 경우
...

2) 비트의 숫자형으로 취급할 경우

SELECT ... WHERE colname = 1; // 1 = 2^0 이므로 첫번째인 a 만 선택한 경우임
SELECT ... WHERE colname >= 1; // 최소한 a 를 선택한 경우
SELECT ... WHERE colname = 3; // 이것은 a 와 b 만 선택한 경우임
SELECT ... WHERE


3) 비트단위로 취급할 경우(bit 연산)

SELECT ... WHERE colname & 1; // 최소한 a 를 선택한 경우
SELECT ... WHERE colname & 3; // 최소한 a 또는 b를 선택한 경우(간단한 OR 연산에 이용)

이와 같이 여러가지 형태로 SQL 문을 만들 수 있다는 것이 그 장점중의 하나입니다.

'DB스토리 > MYSQL' 카테고리의 다른 글

MySQL - DB/테이블 관리 기본 명령어  (0) 2013.11.13
MYSQL 명령어  (0) 2013.10.30
Mysql Workbench - Synchronize Model with Database  (0) 2013.03.18
Mysql Workbench 사용법  (0) 2013.02.18
MYSQL 쿼리  (0) 2013.02.05