MySQL의 저장 프로 시저를 통해 선택하려고 할 때 아래 오류가 발생합니다.
작업 ‘=’에 대한 데이터 정렬 (latin1_general_cs, IMPLICIT)과 (latin1_general_ci, IMPLICIT)의 잘못된 조합
여기서 무엇이 잘못 될지 알고 있습니까?
테이블의 데이터 정렬과 latin1_general_ci
where 절의 열 데이터 정렬은 입니다 latin1_general_cs
.
답변
이는 일반적으로 호환되지 않는 데이터 정렬의 두 문자열을 비교하거나 다른 데이터 정렬의 데이터를 결합 된 열로 선택하려고함으로써 발생합니다.
이 절 COLLATE
에서는 쿼리에 사용 된 데이터 정렬을 지정할 수 있습니다.
예를 들어 다음 WHERE
절은 항상 게시 한 오류를 나타냅니다.
WHERE 'A' COLLATE latin1_general_ci = 'A' COLLATE latin1_general_cs
해결책은 쿼리 내의 두 열에 대해 공유 데이터 정렬을 지정하는 것입니다. 이 COLLATE
절 을 사용하는 예는 다음과 같습니다 .
SELECT * FROM table ORDER BY key COLLATE latin1_general_ci;
다른 옵션은 BINARY
연산자 를 사용하는 것 입니다.
BINARY str은 CAST (str AS BINARY)의 약어입니다.
솔루션은 다음과 같습니다.
SELECT * FROM table WHERE BINARY a = BINARY b;
또는,
SELECT * FROM table ORDER BY BINARY a;
답변
TL; DR
일치하도록 문자열 중 하나 (또는 둘 다)의 데이터 정렬을 변경하거나 COLLATE
표현식에 절을 추가 하십시오.
-
어쨌든이 “콜 레이션”항목은 무엇입니까?
일반적으로 문자 집합 및 데이터 정렬에 설명 된대로 :
문자 집합 기호와 인코딩의 집합입니다. 정렬은 문자 집합의 문자를 비교하기위한 규칙의 집합입니다. 가상의 문자 집합의 예를 통해 구별을 명확하게 만들어 봅시다.
“
A
”,“B
”,“a
”,“b
”의 네 글자로 된 알파벳이 있다고 가정합니다 . 각 문자에는 숫자 “”A
“,”B
“= 1,”a
“= 2,”b
“= 3이 있습니다. 문자”A
“는 기호이고, 숫자 0은 ” “에 대한 인코딩 이며A
네 글자와 해당 인코딩은 문자 세트 입니다.두 문자열 값“
A
”및“B
” 을 비교한다고 가정합니다 . 이 작업을 수행하는 가장 간단한 방법은 인코딩 보는 것입니다 : “0A
“에 대한 1 ”B
“. 0이 1A
보다 작으므로“B
” 이“ ” 보다 작습니다 . 방금 수행 한 작업은 문자 집합에 데이터 정렬을 적용하는 것입니다. 데이터 정렬은 일련의 규칙입니다 (이 경우 하나의 규칙 만 해당).“인코딩 비교” 우리는 가능한 모든 데이터 정렬 중 가장 간단한 것을 바이너리 라고 부릅니다. 데이터 .그러나 소문자와 대문자가 같다고 말하고 싶다면 어떻게해야합니까? (1) 소문자 문자 “치료 : 그런 다음 우리는 적어도 두 가지 규칙을 것
a
“과 ”b
동등”을 ”A
“및 ”B
“; (2) 그런 다음 인코딩을 비교하십시오. 이것을 대소 문자를 구분하지 않습니다. 데이터 정렬이라고합니다. 이진 데이터 정렬보다 조금 더 복잡합니다.실제로 대부분의 문자 세트에는“
A
”및“B
”뿐만 아니라 전체 알파벳, 여러 문자 또는 수천 개의 문자가 포함 된 동부 쓰기 시스템, 많은 특수 기호 및 문장 부호와 같은 많은 문자가 있습니다. 또한 실제로는 대부분의 데이터 정렬에 소문자 구분 여부뿐만 아니라 악센트 구분 여부 ( “액센트”는 독일어 ”Ö
“에서와 같이 문자에 첨부 된 표시 )와 여러 문자에 대한 규칙이 많이 있습니다. 매핑 (예 : 두 독일 데이터 정렬 중 하나에서 “Ö
”=“OE
” 규칙 ).데이터 정렬 효과의 예 아래에 추가 예가 나와 있습니다 .
-
자, 그러나 MySQL은 주어진 식에 사용할 데이터 정렬을 어떻게 결정합니까?
식의 데이터 정렬에 설명 된대로 :
대부분의 문장에서 MySQL이 대조 연산을 해결하기 위해 사용하는 것은 분명합니다. 예를 들어, 다음과 같은 경우 데이터 정렬이 열의 데이터 정렬이라는 것이 분명해야합니다
charset_name
.SELECT x FROM T ORDER BY x; SELECT x FROM T WHERE x = x; SELECT DISTINCT x FROM T;
그러나 피연산자가 여러 개인 경우 모호성이있을 수 있습니다. 예를 들면 다음과 같습니다.
SELECT x FROM T WHERE x = 'Y';
비교시 열
x
또는 문자열 리터럴 의 데이터 정렬을 사용해야'Y'
합니까? 모두x
와'Y'
정렬을, 그래서 어떤 조합이 우선?표준 SQL은 예전에는 “강제력”규칙이라고하는 것을 사용하여 이러한 질문을 해결합니다.
[데 레시아 ]
MySQL은 다음 규칙과 함께 강제성 값을 사용하여 모호성을 해결합니다.
-
보자력 값이 가장 낮은 데이터 정렬을 사용하십시오.
-
양쪽이 동일한 보자력을 갖는 경우 :
-
양면이 유니 코드이거나 양면이 유니 코드가 아닌 경우 오류입니다.
-
측면 중 하나에 유니 코드 문자 집합이 있고 다른쪽에 비 유니 코드 문자 집합이 있으면 유니 코드 문자 집합이있는 쪽이 이기고 자동 문자 집합 변환이 비 유니 코드쪽에 적용됩니다. 예를 들어, 다음 명령문은 오류를 리턴하지 않습니다.
SELECT CONCAT(utf8_column, latin1_column) FROM t1;
의 문자 집합과
utf8
데이터 정렬을 가진 결과를 반환합니다utf8_column
. 의 값은 연결latin1_column
하기utf8
전에 자동으로 변환됩니다 . -
혼합 동일한 문자 집합에서 피연산자과의 작동을하지만,
_bin
정렬하고,_ci
또는_cs
정렬을의_bin
정렬이 사용됩니다. 이는 비 이진 문자열과 이진 문자열을 혼합하는 연산이 피연산자를 이진 문자열로 평가하는 방식과 비슷하지만 데이터 유형이 아닌 데이터 정렬을위한 것입니다.
-
-
-
“부정합 한 데이터 정렬”이란 무엇입니까?
“부정합 한 조합의 콜 레이션”은식이 서로 다른 콜 레이션이지만 동일한 보자력을 가진 두 문자열을 비교할 때 발생하며, 보자기 규칙은 충돌을 해결하는 데 도움이되지 않습니다. 위 인용문의 세 번째 글 머리표에 설명 된 상황입니다.
질문에 주어진 특정 오류
Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '='
는 동일한 보자력을 가진 두 개의 비 유니 코드 문자열 사이에 동등 비교가 있음을 나타냅니다. 또한 데이터 정렬이 명령문에 명시 적으로 제공되지 않고 문자열 소스 (예 : 열 메타 데이터)에서 암시되었음을 나타냅니다. -
그것은 모두 잘되지만, 그러한 오류를 어떻게 해결합니까?
위에서 인용 한 수동 추출에서 알 수 있듯이이 문제는 여러 가지 방법으로 해결할 수 있으며 그 중 두 가지가 합리적이고 권장됩니다.
-
일치하는 문자열이 더 이상 모호하지 않도록 문자열 중 하나 (또는 둘 다)의 데이터 정렬을 변경하십시오.
이 작업을 수행하는 방법은 문자열의 위치에 따라 다릅니다. 리터럴 표현식은
collation_connection
시스템 변수에 지정된 데이터 정렬을 사용합니다 . 테이블의 값은 열 메타 데이터에 지정된 데이터 정렬을 사용합니다. -
하나의 문자열을 강제로 적용하지 않도록합니다.
위의 인용문을 생략했습니다.
MySQL은 다음과 같이 보자력 값을 지정합니다.
따라서
COLLATE
비교에 사용 된 문자열 중 하나에 절을 추가하면 해당 데이터 정렬을 사용해야합니다.
다른 사람들은이 오류를 해결하기 위해 배포 된 경우 매우 나쁜 습관이 될 수 있습니다.
-
문자열 중 하나 (또는 둘 다)가 다른 강제 변환 값을 가지도록하여 하나가 우선합니다.
보자력이 1 인 문자열을 사용
CONCAT()
하거나CONCAT_WS()
결과로 만들 수 있습니다. (저장된 루틴에있는 경우) 매개 변수 / 지역 변수를 사용하면 2의 보자력을 갖는 문자열이 생성됩니다. -
하나는 유니 코드이고 다른 하나는 그렇지 않도록 문자열 중 하나 (또는 둘 다)의 인코딩을 변경하십시오.
이것은 ;로 트랜스 코딩을 통해 수행 될 수 있습니다 . 또는 데이터의 기본 문자 집합 변경 (예 : 열 수정, 리터럴 값 변경 또는 다른 인코딩으로 클라이언트에서 전송 및 문자 집합 소개 자 변경 / 추가)을 통해. 원하는 문자를 새 문자 세트로 인코딩 할 수없는 경우 인코딩을 변경하면 다른 문제가 발생할 수 있습니다.
CONVERT(expr USING transcoding_name)
character_set_connection
character_set_client
-
문자열 중 하나 (또는 둘 다)의 인코딩을 동일하게 변경하고 관련
_bin
데이터 정렬 을 사용하도록 하나의 문자열을 변경하십시오 .인코딩 및 데이터 정렬을 변경하는 방법은 위에 자세히 설명되어 있습니다. 데이터 정렬에서 제공하는 것보다 더 고급 데이터 정렬 규칙을 실제로 적용해야하는 경우이 방법은 거의
_bin
쓸모가 없습니다.
-
답변
미래 Google 직원을위한 토론에 2c를 추가합니다.
varchar 매개 변수를 수신하는 사용자 지정 함수 를 사용할 때 다음과 같은 오류가 발생하는 비슷한 문제를 조사했습니다 .
Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and
(utf8_general_ci,IMPLICIT) for operation '='
다음 쿼리를 사용하십시오.
mysql> show variables like "collation_database";
+--------------------+-----------------+
| Variable_name | Value |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
DB가 utf8_general_ci 를 사용 하고 테이블이 utf8_unicode_ci를 사용하여 정의 되었다는 것을 알 수있었습니다 .
mysql> show table status;
+--------------+-----------------+
| Name | Collation |
+--------------+-----------------+
| my_view | NULL |
| my_table | utf8_unicode_ci |
...
뷰에는 NULL 데이터 정렬이 있습니다. 이 쿼리가 하나의 뷰에 대해 null을 표시하더라도 뷰와 함수에는 데이터 정렬 정의가있는 것으로 보입니다. 사용 된 데이터 정렬은보기 / 기능을 만들 때 정의 된 DB 데이터 정렬입니다.
슬픈 해결책은 db 데이터 정렬을 변경하고 뷰 / 함수를 다시 작성하여 현재 데이터 정렬을 사용하도록하는 것입니다.
-
DB의 데이터 정렬 변경 :
ALTER DATABASE mydb DEFAULT COLLATE utf8_unicode_ci;
-
테이블 데이터 정렬 변경 :
ALTER TABLE mydb CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
이것이 누군가를 도울 수 있기를 바랍니다.
답변
때로는 대량의 데이터가있는 데이터베이스에서 문자 집합을 변환하는 것이 위험 할 수 있습니다. 가장 좋은 옵션은 “이진”연산자를 사용하는 것입니다.
e.g : WHERE binary table1.column1 = binary table2.column1
답변
비슷한 문제가 있었고 FIND_IN_SET 프로 시저를 문자열 변수 와 함께 사용하려고했습니다 .
SET @my_var = 'string1,string2';
SELECT * from my_table WHERE FIND_IN_SET(column_name,@my_var);
오류가 발생했습니다
오류 코드 : 1267. ‘find_in_set’작업에 대한 데이터 정렬 (utf8_unicode_ci, IMPLICIT)과 (utf8_general_ci, IMPLICIT)의 잘못된 조합
짧은 답변:
어떤 collation_YYYY 변수를 변경할 필요, 그냥 올바른 정렬을 추가하지 옆 변수 선언 , 즉
SET @my_var = 'string1,string2' COLLATE utf8_unicode_ci;
SELECT * from my_table WHERE FIND_IN_SET(column_name,@my_var);
긴 대답 :
먼저 데이터 정렬 변수를 확인했습니다.
mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
+----------------------+-----------------+
| collation_database | utf8_general_ci |
+----------------------+-----------------+
| collation_server | utf8_general_ci |
+----------------------+-----------------+
그런 다음 테이블 데이터 정렬을 확인했습니다.
mysql> SHOW CREATE TABLE my_table;
CREATE TABLE `my_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`column_name` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=125 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
이는 내 테이블이 utf8_unicode_ci 로 구성되는 동안 변수가 기본 데이터 정렬 utf8_general_ci 로 구성 되었음을 의미 합니다.
변수 선언 옆에 COLLATE 명령을 추가하여 변수 데이터 정렬이 테이블에 대해 구성된 데이터 정렬과 일치했습니다.
답변
이 스크립트 를 사용하면 모든 데이터베이스와 테이블을 utf8로 변환 할 수 있습니다 .
답변
리터럴이 포함 된 경우 해결책.
Pentaho Data Integration을 사용하고 있으며 SQL 구문을 지정하지 않습니다. 매우 간단한 DB 조회를 사용하면 ” ‘작업’에 대해”잘못된 조합 데이터 정렬 (cp850_general_ci, COERCIBLE) 및 (latin1_swedish_ci, COERCIBLE) “오류가 발생했습니다.
생성 된 코드는 “SELECT DATA_DATE AS latest_DATA_DATE FROM hr_cc_normalised_data_date_v WHERE PSEUDO_KEY =?”입니다.
이야기를 짧게 자르면 조회가 조회되었으며 발행했을 때
mysql> show full columns from hr_cc_normalised_data_date_v;
+------------+------------+-------------------+------+-----+
| Field | Type | Collation | Null | Key |
+------------+------------+-------------------+------+-----+
| PSEUDO_KEY | varchar(1) | cp850_general_ci | NO | |
| DATA_DATE | varchar(8) | latin1_general_cs | YES | |
+------------+------------+-------------------+------+-----+
‘cp850_general_ci’의 출처를 설명합니다.
뷰는 단순히 ‘SELECT’X ‘, …’로 작성되었습니다. 이와 같은 수동 리터럴에 따르면 ‘latin1’및 ‘latin1_general_cs’로 올바르게 정의 된 서버 설정에서 문자 세트 및 데이터 정렬을 상속해야합니다. 내가보기를 만들 때 강요하지 않았다
CREATE OR REPLACE VIEW hr_cc_normalised_data_date_v AS
SELECT convert('X' using latin1) COLLATE latin1_general_cs AS PSEUDO_KEY
, DATA_DATE
FROM HR_COSTCENTRE_NORMALISED_mV
LIMIT 1;
이제 두 열 모두에 latin1_general_cs가 표시되고 오류가 사라졌습니다. 🙂
