이글루 냠냠

namelessja.egloos.com

포토로그



[MYSQL] hexadecimal literal, MySQL에서 16진수 처리하기 DBMS

요즘에 flag 처리를 DB에서 많이 하기 시작해서 발견한 mysql의 새로운 기능!!
mysql에서 16진수 포멧으로 이루어진 문자열을 처리하는 방법에 대한 부분이다.
mysql에서는 16진수 포멧을 가진 문자열을 hexadecimal literal이라고 부르며 별도의 처리 기능을 지원하고 있고,
이를 이용해서 문자열 형태의 flag 처리도 가능하다.
자세한 이론은 맨 마지막의 링크를 참조하는 쪽이 나을지도..?

먼저 예제를 위해 다음 테이블을 만든다.
CREATE TABLE test.arrt (
v1 VARCHAR(16),
v2 IN T
);

INSERT INTO test.arrt(v1, v2) VALUES (16, 16);


이렇게 하면 다음과 같이 나타날 수 있다.
mysql> SELECT * FROM test.arrt;
+------+------+
| v1 | v2 |
+------+------+
| 16 | 16 |
+------+------+
1 rows in set (0.00 sec)


자 그럼 흔히 쓰는 플래그 형태로 검색을 해볼까 한다.
먼저 VARCHAR형태로 저장된 v1에 where절을 사용한 경우이다.
mysql> SELECT * FROM test.arrt WHERE v1 = 0x10;
Empty set (0.00 sec)
16진수 0x10은 10진수로 16인데도 불구하고 결과가 나타나지 않는다!!

그렇다면 이번에는 int형으로 저장된 v2에 where절을 사용해보자.
mysql> SELECT * FROM test.arrt WHERE v2 = 0x10;
+------+------+
| v1 | v2 |
+------+------+
| 16 | 16 |
+------+------+
1 row in set (0.00 sec)
아까와는 다르게 검색이 되었다.

이러한 차이가 나타나는 이유는 mysql의 hexadecimal literal때문이다.
mysql에서는 X'val', x'val', or 0xval의 데이터 형태를 (0..9, A..F)으로 처리한다고 한다.
때문에 검색을 할 때에는 적절한 캐스팅이 필요하다.
v1의 경우에는 자료형이 varchar, 즉 문자열 형태라서 변환 작업이 필요하고,
v2의 경우에는 int형이므로, 이러한 변환 작업이 필요없다.

사용 방법은 2가지가 있는데, 다음과 같다.
mysql> SELECT 0x10, 0x10+0, CAST(0x10 AS UNSIGNED);
+------+--------+------------------------+
| 0x10 | 0x10+0 | CAST(0x10 AS UNSIGNED) |
+------+--------+------------------------+
|  | 16 | 16 |
+------+--------+------------------------+
1 row in set (0.00 sec)
첫 번째에는 이상한 기호가 출력되지만, 두 번째와 세 번째는 제대로 원하는 데이터가 출력된다.

마지막으로 위의 방법으로 v1에 다시금 where조건절을 사용해보자.
mysql> SELECT * FROM test.arrt WHERE v1 = 0x10+0;
+------+------+
| v1 | v2 |
+------+------+
| 16 | 16 |
+------+------+
1 row in set (0.00 sec)


처음으로 mysql 결과를 그대로 붙여넣기 했는데 모양새가 다 깨지는구나...
이글루스에서 이쁘게 보일 방법은 다음 포스팅에 찾......긴 하려나..?

추신. hexadecimal literal과 switch-case문
insert/update 시에 case문을 쓸 경우가 있는데, 이럴 경우 case문의 결과는 문자열로 처리된다.
재미있는점은 다음을 보면 될듯도?
mysql> CREATE TABLE test.arrt(
-> v1 int,
-> v2 int,
-> v3 int
-> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO test.arrt(v1) VALUES(1), (258), (513);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> UPDATE test.arrt
-> SET
-> v2 = CASE
-> WHEN v1 = 1 then 0x100
-> WHEN v1 = 0x102 then 0x200
-> ELSE 0x300
-> END,
-> v3 = CASE
-> WHEN v1 = 1 then 0x100+0
-> WHEN v1 = 0x102 then 0x200+0
-> ELSE 0x300+0
-> END;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0

mysql> SELECT * FROM test.arrt;
+------+------+------+
| v1 | v2 | v3 |
+------+------+------+
| 1 | 0 | 256 |
| 258 | 0 | 512 |
| 513 | 0 | 768 |
+------+------+------+
3 rows in set (0.00 sec)
먼저, v2와 v3 컬럼을 int형으로 추가한 후에 각각 case문을 사용하여 데이터를 넣었다.
v2는 아무런 처리를 하지 않았고, v3은 int형으로 별도의 변환 작업을 거쳐주었다.
결과는 v2에는 모두 0 (문자열이 처리되지 않아 0으로 입력)되었고,
v3에는 정상적으로 숫자형태의 데이터가 들어갔다.
이와같이 hexadecimal literal을 사용할 때에는 자료형 뿐 아니라 구문에도 주의를 해야 한다.

출처 : https://dev.mysql.com/doc/refman/5.0/en/hexadecimal-literals.html

덧글

댓글 입력 영역