테스트 환경 : MySQL 8.0
1. NO PAD 방식
1-1. CHAR 공백 UNIQUE 테스트
공백을 저장 안하므로 'data '를 'data'로 저장한다.(공백제거)
unique 비교시 'data' 와 'data ' 를 다른데이터로 보지만
UNIQUE 값 저장시에 unique 컬럼의 값에 'data' 가 이미 존재한다면
CHAR는 공백을 제거하고 저장하므로 'data ' 가 'data' 가 되어 같은데이터로 인식하여 저장되지 않는다.
공백이 포함된 데이터를 이관시 공백제거 후 같은 데이터가 있는지 점검이 필요하다.
1-2. VARCHAR 공백 UNIQUE 테스트
공백을 저장하여 'data ' 를 'data ' 로 저장한다.(공백유지)
unique 비교시 NOPAD 방식이므로 'data'와 'data '를 다른데이터로 인식한다.
공백이 포함된 데이터를 이관시 공백제거 후 같은 데이터가 있는지 점검이 필요없다.
(하지만, 데이터 자체로 보면 중복이므로 정제가 필요하다.)
2. PAD SPACE 방식
2-1. CHAR 공백 UNIQUE 테스트
공백을 저장 안하므로 'data '를 'data'로 저장한다.(공백제거)
unique 비교시 'data' 와 'data ' 를 같은데이터로 본다. (공백PAD를 채워서 비교)
UNIQUE 값 저장시에 unique 컬럼의 값에 'data' 가 이미 존재한다면
'data '(공백포함) 가 같은데이터로 인식되어 저장되지 않는다.
공백이 포함된 데이터를 이관시 공백제거 후 같은 데이터가 있는지 점검이 필요하다.
2-2. VARCHAR 공백 UNIQUE 테스트
공백을 저장하여 'data ' 를 'data ' 로 저장한다.(공백유지)
unique 비교시 PADSPACE 방식이므로 'data'와 'data '를 같은데이터로 인식한다.
공백이 포함된 데이터를 이관시 공백제거 후 같은 데이터가 있는지 점검이 필요하다.
-- PADSPACE라는 것은 공백PAD를 길이가 큰쪽에 맞춰서 붙여서 공백의 영향없이 비교될 수 있는 것을 의미한다.
3. 결론
COLLATION(정렬) 방식에 따라 비교 방식이 다르다.
NO PAD는 공백을 채우지 않고 비교하여 'data' 와 'data ' 를 다른 데이터로 인식한다.
PAD SPACE 는 공백을 채우고 비교하여 'data' 와 'data ' 를 같은 데이터로 인식한다.
CHAR 타입은 공백을 제거하고 저장하고 VARCHAR 타입은 공백을 저장한다.
* COLLATION 조회
Pad_attribute 속성 값 => NO PAD or PAD SPACE
SHOW COLLATION WHERE Charset = 'utf8mb4';
SELECT COLLATION_NAME, PAD_ATTRIBUTE
FROM INFORMATION_SCHEMA.COLLATIONS
WHERE CHARACTER_SET_NAME = 'utf8mb4';
[TEST]
-- ---------------------------------------------------------------------------------------------------------------------
-- NO PAD 방식
-- ---------------------------------------------------------------------------------------------------------------------
use employees;
SHOW COLLATION WHERE Charset = 'utf8mb4';
-- NO PAD 방식
SHOW COLLATION WHERE collation = 'utf8mb4_0900_ai_ci';
-- 공백이 다르다고 인식한다.
select case when 'data' = 'data ' then 1 else 2 end from dual;
-- varchar 공백 테스트
drop table blink_test1;
create table blink_test1(
col1 varchar(14) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
insert into blink_test1(col1) values('data');
insert into blink_test1(col1) values('data '); -- 공백도 저장한다.
insert into blink_test1(col1) values('data '); -- 공백도 저장한다.
commit;
-- 결과 3건이 나온다.
select * from blink_test1;
-- 결과 1건이 나온다.
select * from blink_test1 where col1 = 'data';
-- 결과 3건이 나온다.
select * from blink_test1 where col1 like 'data%';
-- varchar 공백 pk 테스트(unique 비교시 공백도 저장하므로 'data'와 'data '를 다른데이터로 인식한다)
drop table blink_test2;
create table blink_test2(
col1 varchar(14) NOT NULL
,PRIMARY KEY (col1)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
insert into blink_test2(col1) values('data');
insert into blink_test2(col1) values('data '); -- 공백도 저장한다.
insert into blink_test2(col1) values('data '); -- 공백도 저장한다.
commit;
-- 결과 3건이 나온다.
select * from blink_test2;
-- 결과 1건이 나온다.
select * from blink_test2 where col1 = 'data';
-- 결과 3건이 나온다.
select * from blink_test2 where col1 like 'data%';
-- varchar 공백 pk 테스트(unique 비교시 공백도 저장하므로 'data'와 'data '를 다른데이터로 인식한다)
drop table blink_test3;
create table blink_test3(
col1 varchar(14) NOT NULL
,col2 varchar(14) NOT NULL
,PRIMARY KEY (col1, col2)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
insert into blink_test3(col1,col2) values('data','data2');
insert into blink_test3(col1,col2) values('data','data2 ');
insert into blink_test3(col1,col2) values('data','data2 ');
commit;
-- 결과 3건이 나온다.
select * from blink_test3;
-- 결과 1건이 나온다.
select * from blink_test3 where col1 = 'data' and col2 = 'data2';
-- 결과 3건이 나온다.
select * from blink_test3 where col1 = 'data' and col2 like 'data%';
-- char 공백 pk 테스트(unique 비교시 공백을 저장 안하므로 'data'와 'data '를 같은데이터로 인식한다)
drop table blink_test4;
create table blink_test4(
col1 char(14) NOT NULL
,col2 char(14) NOT NULL
,PRIMARY KEY (col1, col2)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
insert into blink_test4(col1,col2) values('data','data2 '); -- 공백을 제거하고 저장한다.
insert into blink_test4(col1,col2) values('data','data2'); -- Duplicate entry 'data-data2' for key 'blink_test4.PRIMARY'
insert into blink_test4(col1,col2) values('data','data2 ');-- Duplicate entry 'data-data2' for key 'blink_test4.PRIMARY'
commit;
-- 결과 1건이 나온다.
select * from blink_test4;
-- 결과 1건이 나온다.
select * from blink_test4 where col1 = 'data' and col2 = 'data2';
-- 결과 0건이 나온다.
select * from blink_test4 where col1 = 'data ' and col2 = 'data2 ';
-- char 공백 테스트(공백을 저장 안하므로 'data'와 'data '를 같은데이터로 인식한다)
drop table blink_test5;
create table blink_test5(
col1 char(14) NOT NULL
,col2 char(14) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ;
insert into blink_test5(col1,col2) values('data','data2');
insert into blink_test5(col1,col2) values('data','data2 '); -- 공백을 제거하고 저장한다.
insert into blink_test5(col1,col2) values('data','data2 ');-- 공백을 제거하고 저장한다.
commit;
-- 결과 3건이 나온다.
select * from blink_test5;
-- 결과 3건이 나온다.
select * from blink_test5 where col1 = 'data' and col2 = 'data2';
-- 결과 0건이 나온다.
select * from blink_test5 where col1 = 'data' and col2 = 'data2 ';
-- 결과 3건이 나온다.
select * from blink_test5 where col1 = 'data' and col2 like 'data2%';
select cast('data' as char) from dual;
select cast('data' as char) = cast('data ' as char) ; -- 0
select cast('data' as varchar) = cast('data ' as varchar);
-- ---------------------------------------------------------------------------------------------------------------------
-- PAD SPACE 방식
-- ---------------------------------------------------------------------------------------------------------------------
-- PADSPACE라는 것은 공백PAD를 길이가 큰쪽에 맞춰서 붙여서 공백의 영향없이 비교될 수 있는 것을 의미한다.
SHOW COLLATION WHERE collation = 'utf8mb4_bin';
show COLLATION where charset = 'utf8mb4';
-- varchar 공백 테스트
drop table blink_test1;
create table blink_test1(
col1 varchar(14) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ;
insert into blink_test1(col1) values('data');
insert into blink_test1(col1) values('data '); -- 공백도 저장한다.
insert into blink_test1(col1) values('data '); -- 공백도 저장한다.
commit;
-- 결과 3건이 나온다.
select * from blink_test1;
-- 결과 1건이 나온다. --> 결과 3건이 나온다.
select * from blink_test1 where col1 = 'data';
-- [추가]
-- 결과 3건이 나온다. PADSPACE를 큰것에 맞춰서 비교한다.
select * from blink_test1 where col1 = 'data ';
-- 결과 3건이 나온다.
select * from blink_test1 where col1 like 'data%';
-- varchar 공백 pk 테스트(unique 비교시 공백을 채워서 비교하므로 'data'와 'data '를 같은 데이터로 인식한다)
drop table blink_test2;
create table blink_test2(
col1 varchar(14) NOT NULL
,PRIMARY KEY (col1)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ;
insert into blink_test2(col1) values('data');
insert into blink_test2(col1) values('data '); -- UNIQUE 체크를 위해서 공백 채워서 비교하여 저장하지 못한다.
-- 18:33:00 insert into blink_test2(col1) values('data ') Error Code: 1062. Duplicate entry 'data ' for key 'blink_test2.PRIMARY' 0.000 sec
insert into blink_test2(col1) values('data '); -- UNIQUE 체크를 위해서 공백 채워서 비교하여 저장하지 못한다.
-- 18:33:31 insert into blink_test2(col1) values('data ') Error Code: 1062. Duplicate entry 'data ' for key 'blink_test2.PRIMARY' 0.000 sec
commit;
-- 결과 3건이 나온다. --> 결과 1건이 나온다.
select * from blink_test2;
-- 결과 1건이 나온다.
select * from blink_test2 where col1 = 'data';
-- 결과 3건이 나온다. --> 결과 1건이 나온다.
select * from blink_test2 where col1 like 'data%';
-- varchar 공백 pk 테스트(unique 비교시 공백도 저장하므로 'data'와 'data '를 같은 데이터로 인식한다)
drop table blink_test3;
create table blink_test3(
col1 varchar(14) NOT NULL
,col2 varchar(14) NOT NULL
,PRIMARY KEY (col1, col2)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ;
insert into blink_test3(col1,col2) values('data','data2 '); -- 공백을 저장한다.
insert into blink_test3(col1,col2) values('data','data2'); -- Error Code: 1062. Duplicate entry 'data-data2 ' for key 'blink_test3.PRIMARY'
insert into blink_test3(col1,col2) values('data','data2 ');-- Error Code: 1062. Duplicate entry 'data-data2 ' for key 'blink_test3.PRIMARY'
commit;
-- 결과 3건이 나온다. --> 결과 1건이 나온다.
select * from blink_test3;
-- 결과 1건이 나온다.
select * from blink_test3 where col1 = 'data' and col2 = 'data2';
-- [추가]
-- 결과 1건이 나온다. (공백을 추가해도 같은데이터로 본다)
select * from blink_test3 where col1 = 'data ' and col2 = 'data2 ';
-- 결과 3건이 나온다. --> 결과 1건이 나온다.
select * from blink_test3 where col1 = 'data' and col2 like 'data%';
-- char 공백 pk 테스트(unique 비교시 공백을 저장 안하므로 'data'와 'data '를 같은데이터로 인식한다)
drop table blink_test4;
create table blink_test4(
col1 char(14) NOT NULL
,col2 char(14) NOT NULL
,PRIMARY KEY (col1, col2)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ;
insert into blink_test4(col1,col2) values('data','data2 '); -- 공백을 제거하고 저장한다.
insert into blink_test4(col1,col2) values('data','data2'); -- Duplicate entry 'data-data2' for key 'blink_test4.PRIMARY'
insert into blink_test4(col1,col2) values('data','data2 ');-- Duplicate entry 'data-data2' for key 'blink_test4.PRIMARY'
commit;
-- 결과 1건이 나온다.
select * from blink_test4;
-- 결과 1건이 나온다.
select * from blink_test4 where col1 = 'data' and col2 = 'data2';
-- 결과 0건이 나온다. --> 결과 1건이 나온다.
select * from blink_test4 where col1 = 'data ' and col2 = 'data2 ';
-- char 공백 테스트(공백을 저장 안하므로 'data'와 'data '를 같은데이터로 인식한다)
drop table blink_test5;
create table blink_test5(
col1 char(14) NOT NULL
,col2 char(14) NOT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ;
insert into blink_test5(col1,col2) values('data','data2');
insert into blink_test5(col1,col2) values('data','data2 '); -- 공백을 제거하고 저장한다.
insert into blink_test5(col1,col2) values('data','data2 ');-- 공백을 제거하고 저장한다.
commit;
-- 결과 3건이 나온다.
select * from blink_test5;
-- 결과 3건이 나온다.
select * from blink_test5 where col1 = 'data' and col2 = 'data2';
-- 결과 0건이 나온다. --> 결과 3건이 나온다. 공백을 채워서 비교하여 'data2' 와 'data2 '를 같은 데이터로 인식한다.
select * from blink_test5 where col1 = 'data' and col2 = 'data2 ';
-- 결과 3건이 나온다.
select * from blink_test5 where col1 = 'data' and col2 like 'data2%';
-----------------------------------------------------------------------------------------------------------------------