Loading...
MySQL 9.5 Reference Manual 9.5의 12.8.4 Collation Coercibility in Expressions의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
대부분의 문장에서는 비교 연산을 수행할 때 MySQL이 어떤 collation을 사용하는지가 명백합니다. 예를 들어 다음과 같은 경우, collation은 컬럼 x의 collation이라는 것이 분명합니다:
1SELECT x FROM T ORDER BY x; 2SELECT x FROM T WHERE x = x; 3SELECT DISTINCT x FROM T;
그러나 피연산자가 여러 개이면 모호성이 발생할 수 있습니다. 예를 들어, 다음 문장은 컬럼 x와 문자열 리터럴 'Y' 간의 비교를 수행합니다:
1SELECT x FROM T WHERE x = 'Y';
x와 'Y'가 같은 collation을 가진다면, 비교에 사용할 collation에 모호성은 없습니다. 하지만 둘이 서로 다른 collation을 가진다면, 비교에서 x의 collation을 사용해야 할지, 아니면 'Y'의 collation을 사용해야 할지 문제가 됩니다. x와 'Y' 모두 collation을 가지므로, 어떤 collation이 우선해야 할까요?
collation의 혼합은 비교 이외의 문맥에서도 발생할 수 있습니다. 예를 들어, CONCAT(x,'Y')와 같은 다중 인자 연결 연산은 인자들을 결합하여 하나의 문자열을 생성합니다. 이 결과는 어떤 collation을 가져야 할까요?
이와 같은 질문을 해결하기 위해, MySQL은 한 항목의 collation이 다른 항목의 collation으로 coercion(강제 변경)될 수 있는지 여부를 검사합니다. MySQL은 다음과 같이 coercibility 값을 부여합니다:
명시적인 COLLATE 절은 coercibility 0 (전혀 coercible하지 않음)을 가집니다.
컬럼, 저장 루틴 파라미터, 로컬 변수의 collation은 coercibility 2를 가집니다.
“시스템 상수”(예:
USER() 또는
VERSION()과 같은 함수가 반환하는 문자열)는 coercibility 3을 가집니다.
리터럴의 collation은 coercibility 4를 가집니다.
숫자 또는 시간 값의 collation은 coercibility 5를 가집니다.
NULL 또는 NULL에서 파생된 표현식은 coercibility 6을 가집니다.
두 문자열의 연결은, 두 인자 중 더 강한 strength를 상속합니다. 단, 두 문자열이 동일한 strength와 동일한 문자 집합을 가지지만 서로 다른 collation을 가질 경우, coercibility는 7이 됩니다.
COERCIBILITY() 함수를 사용하는 예는 다음과 같습니다:
1mysql> SET @x = 'x' COLLATE utf8mb4_0900_ai_ci; 2Query OK, 0 rows affected (0.00 sec) 3 4mysql> SET @y = 'y' COLLATE utf8mb4_0900_as_cs; 5Query OK, 0 rows affected (0.00 sec) 6 7mysql> SELECT COERCIBILITY(CONCAT(@x, @y)); 8+------------------------------+ 9| COERCIBILITY(CONCAT(@x, @y)) | 10+------------------------------+ 11| 7 | 12+------------------------------+ 131 row in set (0.00 sec)
참고
1이라는 coercibility 값은 MySQL 9.5에서는 사용되지 않지만, 여전히 이전 버전과의 호환성을 위해 유효한 값으로 간주됩니다. (Bug #37285902)
MySQL은 모호성을 해소하기 위해 coercibility 값을 다음 규칙과 함께 사용합니다:
coercibility 값이 가장 낮은 collation을 사용합니다.
양쪽이 동일한 coercibility를 가진다면, 다음 규칙이 적용됩니다:
양쪽이 모두 유니코드이거나, 양쪽 모두 유니코드가 아니면 에러입니다.
한쪽은 유니코드 문자 집합을 가지고 다른 한쪽은 비유니코드 문자 집합을 가지는 경우, 유니코드 문자 집합을 가진 쪽이 우선하며, 비유니코드 쪽에는 자동 문자 집합 변환이 적용됩니다. 예를 들어 다음 문장은 에러를 반환하지 않습니다:
1SELECT CONCAT(utf8mb4_column, latin1_column) FROM t1;
이 문장은 문자 집합이 utf8mb4이고 utf8mb4_column과 동일한 collation을 갖는 결과를 반환합니다. latin1_column 값은 연결 전에 자동으로 utf8mb4로 변환됩니다.
동일한 문자 집합의 피연산자 간 연산에서, _bin collation과 _ci 또는 _cs collation이 섞여 있는 경우, _bin collation이 사용됩니다. 이는 비바이너리와 바이너리 문자열이 섞인 연산에서 피연산자를 데이터 타입이 아닌 collation에 대해 바이너리 문자열로 평가하는 방식과 유사합니다.
자동 변환은 SQL 표준에는 없지만, 표준에서는 각 문자 집합이 (지원되는 문자 측면에서) 유니코드의 “부분집합”이라고 규정하고 있습니다. “슈퍼셋에 적용되는 것은 서브셋에도 적용될 수 있다”는 잘 알려진 원칙에 따라, 우리는 유니코드용 collation이 비유니코드 문자열과의 비교에도 적용될 수 있다고 봅니다. 보다 일반적으로, MySQL은 문자 집합 레퍼토리 개념을 사용하는데, 이는 경우에 따라 문자 집합 간의 부분집합 관계를 판단하고, 그렇지 않으면 에러를 발생시킬 연산에서 피연산자 변환을 가능하게 해 줍니다. 자세한 내용은 Section 12.2.1, “Character Set Repertoire”를 참고하십시오.
다음 표는 앞서 나온 규칙들이 적용되는 몇 가지 예를 보여줍니다.
| Comparison | Collation Used |
|---|---|
column1 = 'A' | column1의 collation 사용 |
column1 = 'A' COLLATE x | 'A' COLLATE x의 collation 사용 |
column1 COLLATE x = 'A' COLLATE y | Error |
문자열 표현식의 coercibility를 확인하려면
COERCIBILITY() 함수를 사용합니다 (자세한 내용은
Section 14.15, “Information Functions” 참고):
1mysql> SELECT COERCIBILITY(_utf8mb4'A' COLLATE utf8mb4_bin); 2 -> 0 3mysql> SELECT COERCIBILITY(VERSION()); 4 -> 3 5mysql> SELECT COERCIBILITY('A'); 6 -> 4 7mysql> SELECT COERCIBILITY(1000); 8 -> 5 9mysql> SELECT COERCIBILITY(NULL); 10 -> 6
CONCAT(1, 'abc') 표현식에서 인자 1의 경우와 같이, 숫자 또는 시간 값을 문자열로 암시적으로 변환하는 경우, 결과는 문자(비바이너리) 문자열이 되며, 그 문자 집합과 collation은
character_set_connection 및
collation_connection 시스템 변수에 의해 결정됩니다. 자세한 내용은 Section 14.3, “Type Conversion in Expression Evaluation”을 참고하십시오.
12.8.3 Character Set and Collation Compatibility
12.8.5 The binary Collation Compared to _bin Collations