MySQL PRIMARY KEY 대소문자 - MySQL PRIMARY KEY daesomunja

MySQL PRIMARY KEY 대소문자 - MySQL PRIMARY KEY daesomunja

MySQL은 비교나 검색을 수행할 때
기본적으로 대소문자 구분 없이 비교 및 검색이 가능하다.

이에 따라 아이디나 패스워드 등 대소문자가 엄격히 구분되어야 하는 경우
서로 다른 값으로 인식되도록 처리가 필요하다.

예시 1 - SELECT절에서 대소문자 비교

SELECT 'X' = 'x';

실행결과 - 대문자와 소문자의 비교 결과가 true이다.

1

예시 2 - WHERE절에서 대소문자 비교

SELECT 'ID' AS ID FROM MEMBER WHERE ID = 'id'

실행결과 - 소문자로 검색해도 검색결과가 도출된다.

ID

BINARY 문자열 타입은
문자가 아닌 바이트를 기준으로 비교나 검색을 할 수 있다.

방법 1. 테이블 생성 시 해당 필드에 BINARY 타입 사용

MySQL에서 지원하는 BINARY타입에는 BINARY, VARBINARY, BLOB이 있다.

예시 - 테이블 생성 시 해당 필드 BINARY 타입으로 생성

CREATE TABLE `MEMBER` ( `ID` varbinary(10) NOT NULL, PRIMARY KEY (`ID`) )

방법 2. 테이블 생성 시 해당 필드에 BINARY 옵션 적용

예시 - 테이블 생성 시 해당 필드에 BINARY 옵션 추가

CREATE TABLE `MEMBER` ( `ID` varchar(10) binary NOT NULL, PRIMARY KEY (`ID`) )

방법 3. BINARY 연산자 이용

예시 - 쿼리 작성 시 SELECT절에서 비교

SELECT BINARY 'ID' = 'id'

실행결과 - 대문자와 소문자의 비교 결과가 false이다.

0

방법 4. BINARY 함수 이용

예시 - 쿼리 작성 시 WHERE절에서 비교

SELECT 'ID' AS ID FROM MEMBER WHERE BINARY(ID) = 'id'

실행결과

검색결과 없음.

일반적인 CHAR, VARCHAR, TEXT 타입의 컬럼에 조건 비교를 하면 대소문자 구분을 하지 않는다.
조건에서 대소문자 구분이 필요한 경우 BINARY 함수를 사용하면 된다.

SELECT ID FROM MEMBER WHERE ID = 'ref';
SELECT ID FROM MEMBER WHERE BINARY(ID) = 'Ref';

MySQL 공식 문서에는 아래와 같이 언급하고 있다.

For nonbinary strings (CHAR, VARCHAR, TEXT), string searches use the collation of the comparison operands.
For binary strings (BINARY,VARBINARY, BLOB), comparisons use the numeric values of the bytes in the operands;
this means that for alphabetic characters, comparisons will be case sensitive.

만약 BINARY 함수를 사용하지 않고 대소문자를 구분하고 싶다면, BINARY 타입으로 테이블을 생성하면 된다.

CREATE TABLE `user` (
  `id` varbinary(20) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

이때 주의할 점은 BLOB으로 처리되어 일반적인 문자열로 변환할 때 또 다른 작업이 필요하다. 이럴 때는 아래와 같이 BINARY 옵션을 추가한다.

CREATE TABLE `user` (
  `id` varchar(20) binary DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

이렇게 테이블을 생성하면 VARCHAR 타입이면서 대소문자를 구분할 수 있게 된다.

Ű �ΰ��� �����ؼ� P.K�� ��Ҵµ�
��ҹ��� ������ ���ϴ� �� �������� �³��� ??

mysql> create table TS_TABLE
    -> ( CODE1  varchar(10) not null,
    ->  CODE2  char(3) not null,
    ->  DATA  int  ,
    ->  primary key (CODE1,CODE2));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into TS_TABLE values ('AAA','001',10);
Query OK, 1 row affected (0.00 sec)

mysql> insert into TS_TABLE values ('aaa','001',10); 
ERROR 1062: Duplicate entry 'aaa-001' for key 1

�ƴ� Ư���� ��ҹ��� �����϶�� �ϴ� �� �ֳ���??

Oracle �̳� ��Ÿ DB������ �и��� �����ϴ� ������ �˰� �ֽ��ϴ�.

  • �亯ä����
    MySQL PRIMARY KEY 대소문자 - MySQL PRIMARY KEY daesomunja
    100%
  • ��õ 0 �� ������ ������ �峪��?
  • ����õ 0 �� ������ ������ �ȵ���.


DB/MySQL

2017. 4. 4. 14:18

MySQL에서 select 쿼리 수행시 신기(?)한 부분을 발견해서 정리해 본다.

들어가며...

(Ver. 5.6)

MySQL에서 테이블명 또는 컬럼명에서는 대소문자를 구별한다는 것은 잘 알려진 사실이다.

그 이유는 테이블 또는 컬럼명이 파일로 관리되기 때문인데, 윈도우에서는 이슈가 없으나 Unix 계열에서는 대소문자 구분이 필요하기 때문이다. 그렇다면 문자열 컬럼(VARCHAR, CHAR, TEXT 등)에 저장된 내용은 어떻게 될까?

문자열 컬럼에서 대소문자 처리

아래와 같이 id, name 컬럼을 가진 user 테이블이 있다고 가정하자.

CREATE TABLE `user` (

`id` varchar(20)DEFAULT NULL,

`name` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

데이터 입력

insert into user(id, name)

values ('test', 'test');

insert into user(id, name)

values ('TEST', 'TEST’);

id=‘test’인 row를 조회해 보자.

select * from user where id = 'test';


대문자 TEST도 함께 조회가 된다. 그럼 소문자 test만 조회하려면 어떻게 할까?

먼저 MySQL 문자열 타입에는 두 가지 카테고리로 구분할 수 있다.

  • nonbinary: CHAR, VARCHAR, TEXT
  • binary: BINARY, VARBINARY, BLOB

For nonbinary strings (CHARVARCHARTEXT), string searches use the collation of the comparison operands. For binary strings (BINARY,VARBINARYBLOB), comparisons use the numeric values of the bytes in the operands; this means that for alphabetic characters, comparisons will be case sensitive.

즉, 위에서 테이블을 생성할 때 VARCHAR로 생성했기 때문에 문자열 검색시 대소문자를 구분하지 않는다.

만약 구분하고자 한다면 binary 타입을 활용해야 한다.

BINARY 타입 테스트

CREATE TABLE `user2` (

`id` varbinary(20) DEFAULT NULL,

`name` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into user2(id, name)

values ('test', 'test');

insert into user2(id, name)

values ('TEST', 'TEST’);

select * from user2 where id = 'test';



varbinary로 설정을 하면 대소문자를 구분하여 조회를 할 수 있다.

하지만 결과 캡쳐화면에서도 확인할 수 있듯이 BLOB으로 처리됨을 확인할 수 있다. BLOB을 일반적인 문자열로 변환하기에는 또 다른 작업이 필요하므로 불편할 수 있다.

이럴 때에는 컬럼에 binary 옵션을 주도록 하자.

CREATE TABLE `user3` (

`id` varchar(20) binary DEFAULT NULL,

`name` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into user3(id, name)

values ('test', 'test');

insert into user3(id, name)

values ('TEST', 'TEST');

select * from user3 where id = 'test';


varchar 타입이면서 대소문자를 구분할 수 있게 된다.

꼭 컬럼 생성시 타입이나 옵션을 주지 않더라도 문자열 조회시 지정하는 방법도 있다.

select * from user where id = ‘test’ COLLATE utf8_bin;

위 방법은 문자열 비교 쿼리마다 다 수정해 주어야 하는 단점이 있지만 운영중인 DB의 컬럼 변경시 risk를 줄일 수 있다는 장점도 있다.(application 배포만 하면 적용됨) 

  • https://dev.mysql.com/doc/refman/5.6/en/case-sensitivity.html
  • http://deadfile.tistory.com/entry/MySQL%EC%97%90%EC%84%9C%EC%9D%98-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EC%B2%98%EB%A6%AC