'='작업에 대한 데이터 정렬 (utf8_unicode_ci, IMPLICIT)과 (utf8_general_ci, IMPLICIT)의 잘못된 조합


160

MySql의 오류 메시지 :

Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='

다른 게시물을 살펴본 결과이 문제를 해결할 수 없었습니다. 영향을받는 부분은 다음과 유사합니다.

CREATE TABLE users (
    userID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    firstName VARCHAR(24) NOT NULL,
    lastName VARCHAR(24) NOT NULL,
    username VARCHAR(24) NOT NULL,
    password VARCHAR(40) NOT NULL,
    PRIMARY KEY (userid)
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

CREATE TABLE products (
    productID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    title VARCHAR(104) NOT NULL,
    picturePath VARCHAR(104) NULL,
    pictureThumb VARCHAR(104) NULL,
    creationDate DATE NOT NULL,
    closeDate DATE NULL,
    deleteDate DATE NULL,
    varPath VARCHAR(104) NULL,
    isPublic TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
    PRIMARY KEY (productID)
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

CREATE TABLE productUsers (
    productID INT UNSIGNED NOT NULL,
    userID INT UNSIGNED NOT NULL,
    permission VARCHAR(16) NOT NULL,
    PRIMARY KEY (productID,userID),
    FOREIGN KEY (productID) REFERENCES products (productID) ON DELETE RESTRICT ON UPDATE NO ACTION,
    FOREIGN KEY (userID) REFERENCES users (userID) ON DELETE RESTRICT ON UPDATE NO ACTION
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

내가 사용하는 저장 프로 시저는 다음과 같습니다.

CREATE PROCEDURE updateProductUsers (IN rUsername VARCHAR(24),IN rProductID INT UNSIGNED,IN rPerm VARCHAR(16))
BEGIN
    UPDATE productUsers
        INNER JOIN users
        ON productUsers.userID = users.userID
        SET productUsers.permission = rPerm
        WHERE users.username = rUsername
        AND productUsers.productID = rProductID;
END

PHP로 테스트했지만 SQLyog에서도 동일한 오류가 발생합니다. 또한 전체 DB를 다시 작성하는 것을 테스트했지만 좋지 않습니다.

도움을 주시면 감사하겠습니다.

답변:


220

저장 프로 시저 매개 변수의 기본 데이터 정렬은 데이터 정렬을 utf8_general_ci혼합 할 수 없으므로 다음 네 가지 옵션이 있습니다.

옵션 1 : COLLATE입력 변수에 추가 하십시오.

SET @rUsername = aname COLLATE utf8_unicode_ci; -- COLLATE added
CALL updateProductUsers(@rUsername, @rProductID, @rPerm);

옵션 2 : 절에 추가 COLLATE하십시오 WHERE.

CREATE PROCEDURE updateProductUsers(
    IN rUsername VARCHAR(24),
    IN rProductID INT UNSIGNED,
    IN rPerm VARCHAR(16))
BEGIN
    UPDATE productUsers
        INNER JOIN users
        ON productUsers.userID = users.userID
        SET productUsers.permission = rPerm
        WHERE users.username = rUsername COLLATE utf8_unicode_ci -- COLLATE added
        AND productUsers.productID = rProductID;
END

옵션 3 : IN매개 변수 정의에 추가하십시오 .

CREATE PROCEDURE updateProductUsers(
    IN rUsername VARCHAR(24) COLLATE utf8_unicode_ci, -- COLLATE added
    IN rProductID INT UNSIGNED,
    IN rPerm VARCHAR(16))
BEGIN
    UPDATE productUsers
        INNER JOIN users
        ON productUsers.userID = users.userID
        SET productUsers.permission = rPerm
        WHERE users.username = rUsername
        AND productUsers.productID = rProductID;
END

옵션 4 : 필드 자체를 변경하십시오.

ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci;

유니 코드 순서로 데이터를 정렬 해야하는 경우가 아니라면 utf8_general_ci코드 변경이 필요하지 않고 정렬 속도가 약간 빨라지므로 데이터 정렬 을 사용하도록 모든 테이블을 변경하는 것이 좋습니다 .

업데이트 : utf8mb4 / utf8mb4_unicode_ci는 이제 선호되는 문자 세트 / 데이터 정렬 방법입니다. 성능 향상은 무시할 수 있으므로 utf8_general_ci는 권장되지 않습니다. 참조 https://stackoverflow.com/a/766996/1432614를


1
COLLATE utf8_unicode_ci문자열 상수 에 추가 할 수도 있습니다 : SET @EMAIL = 'abc@def.com' COLLATE utf8_unicode_ci;. 콘솔 기본 인코딩이 문자열 상수의 데이터 정렬에 적용되는 콘솔에서 스크립트를 실행하는 경우 특히 유용합니다.
gaborsch

또는 utf8_general_ci로 데이터베이스를 삭제하고 새로 만듭니다. 대조.
Oleksii Kyslytsyn

2
나중에 참조 할 수 있도록 두 데이터 정렬의 차이점을 이해하지 않으면 모든 테이블을 utf8_general_ci로 변경하지 마십시오.
Manatax

1
@GaborSch 문자열 변수에 collate를 추가하는 것이 해결책이었습니다. 나는 귀하의 의견을 발견하기 전에 그것에 대한 자세한 답변을 썼습니다.
nkatsar

(utf8mb4_unicode_ci, IMPLICIT)대신을 제외하고 동일한 오류가 발생 (utf8_unicode_ci, IMPLICIT)합니다. 파이썬을 사용하여 웹에서 데이터를 긁어 내고 스크랩 된 데이터로 CSV 파일을 만든 다음 서버에서 PHP 파일로 처리하여 데이터베이스에 데이터를 업로드합니다. 모든 MySQL 테이블 / 열은로 정렬됩니다 utf8mb4_unicode_ci. utf8python / csv에서 와 같이 데이터를 인코딩하기 때문에 문제가 발생할 수 있습니까?
oldboy

27

나는 반나절 동안 utf8_unicode_ci와 utf8_general_ci 사이의 충돌과 동일한 "잘못된 조합 데이터 정렬"오류에 대한 답변을 검색했습니다.

데이터베이스의 일부 열이 utf8_unicode_ci 특별히 정렬 되지 않은 것으로 나타 났습니다 . mysql이 utf8_general_ci 열을 암시 적으로 대조 한 것 같습니다. .

특히 'SHOW CREATE TABLE table1'쿼리를 실행하면 다음과 같은 결과가 출력됩니다.

| table1 | CREATE TABLE `table1` (
`id` int(11) NOT NULL,
`col1` varchar(4) CHARACTER SET utf8 NOT NULL,
`col2` int(11) NOT NULL,
PRIMARY KEY (`col1`,`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |

'col1'varchar (4) CHARACTER SET utf8 NOT NULL 에는 데이터 정렬이 지정되어 있지 않습니다. 그런 다음 다음 쿼리를 실행했습니다.

ALTER TABLE table1 CHANGE col1 col1 VARCHAR(4) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;

이로 인해 "잘못된 조합 데이터 정렬"오류가 해결되었습니다. 이것이 다른 누군가를 도울 수 있기를 바랍니다.


7
감사. 'SHOW CREATE TABLE'은 문제의 근본 원인을 이해하고 해결하는 가장 쉬운 방법입니다.
joro

2
또한 지정 참고 COLLATE전체 테이블 (IE 용하는 ALTER TABLE table1 CHARSET utf8 COLLATE utf8_unicode_ci) 문제가 해결되지 않습니다 , 각 (문제가) 열에 대해 수행되어야한다.
Skippy le Grand Gourou

6

비슷한 문제가 있었지만 쿼리 매개 변수가 변수 eg를 사용하여 설정되었을 때 내부 절차가 발생했습니다 SET @value='foo'.

이 문제의 원인이 일치하지 collation_connection않고 데이터베이스 데이터 정렬이 있습니다. collation_connection일치하도록 변경 되어 collation_database문제가 해결되었습니다. 나는 이것이 매개 변수 / 값 뒤에 COLLATE를 추가하는 것보다 더 우아한 접근법이라고 생각합니다.

요약하면 : 모든 데이터 정렬이 일치해야합니다. 사용 SHOW VARIABLES하고 있는지 확인 collation_connection하고 collation_database일치 (또한 사용하여 테이블 정렬을 확인 SHOW TABLE STATUS [table_name]).


1
동일한 문제가 발생했습니다. 변수 선언에서 데이터 정렬을 직접 설정하여 collation_YYY 변수를 변경하지 않았습니다. SET @my_var = 'string1,string2' COLLATE utf8_unicode_ci;
nkatsar

5

@bpile 답변과 약간 비슷한 나의 경우는 my.cnf 항목 설정 collation-server = utf8_general_ci이었습니다. 그것을 깨달은 후 (그리고 위의 모든 것을 시도한 후에) 데이터베이스를 utf8_unicode_ci 대신 utf8_general_ci로 강제 전환했습니다.

ALTER DATABASE `db` CHARACTER SET utf8 COLLATE utf8_general_ci;

1
구성이 너무 많이 퍼져 있다는 것은 이상합니다. 모든 데이터 정렬 기본값은 같은 위치에 설정해야합니다.
Manatax

0

내 경우에는 다음과 같은 오류가 있습니다.

'='작업에 대한 데이터 정렬 (utf8_general_ci, IMPLICIT)과 (utf8_unicode_ci, IMPLICIT)의 잘못된 조합

$ this-> db-> select ( "users.username as matric_no, CONCAT (users.surname, '', users.first_name, '', users.last_name) as fullname")-> 가입 ( 'users', 'users .username = classroom_students.matric_no ','left ')-> where ('classroom_students.session_id ', $ session)-> where ('classroom_students.level_id ', $ level)-> where ('classroom_students.dept_id ', $ dept );

몇 주 동안 Google 검색을 한 후 비교하는 두 필드가 다른 데이터 정렬 이름으로 구성되어 있음을 알았습니다. 첫 번째는 사용자 이름이 utf8_general_ci이고 두 번째는 utf8_unicode_ci이므로 두 번째 테이블의 구조로 돌아가 두 번째 필드 (matric_no)를 utf8_general_ci로 변경하여 매력처럼 작동했습니다.


0

동일한 문제 ( 1 , 2 , 3 , 4 ) 에 대해 엄청난 수의 질문을 찾았음에도 불구하고 여기서조차도 성능을 고려한 답을 찾지 못했습니다.

여러 작업 솔루션이 이미 제공되었지만 성능을 고려하고 싶습니다.

편집 : 옵션 1에 성능 문제가 없음을 지적한 Manatax에게 감사드립니다.

사용 옵션 1과 2 는 일명 COLLATE의 칼럼에 정의 된 인덱스가 원인이 사용되지 않습니다 원인 캐스트 방식, 잠재적 인 병목 현상으로 이어질 수 있습니다 전체 검사를 .

옵션 3을 시도하지 않았지만 옵션 1과 동일한 결과를 겪을 것입니다. 2 .

마지막으로 옵션 4 는 실행 가능한 경우 매우 큰 테이블에 가장 적합한 옵션입니다. 원래 데이터 정렬에 의존하는 다른 사용법이 없음을 의미합니다.

이 간단한 쿼리를 고려하십시오.

SELECT 
    *
FROM
    schema1.table1 AS T1
        LEFT JOIN
    schema2.table2 AS T2 ON T2.CUI = T1.CUI
WHERE
    T1.cui IN ('C0271662' , 'C2919021')
;

원래 예에서 더 많은 조인이있었습니다. 물론 table1과 table2는 다른 데이터 정렬을 갖습니다. 한 부씩 인쇄 사용 캐스트에 연산자를, 그것을 사용하지 않는 인덱스로 이어질 것입니다.

아래 그림에서 sql 설명을 참조하십시오.

COLLATE 캐스트 사용시 시각적 쿼리 설명

반면에 옵션 4 는 가능한 인덱스를 활용하여 빠른 쿼리를 유발할 수 있습니다.

아래 그림에서 옵션 4를 적용한 후 동일한 쿼리가 실행되는 것을 볼 수 있습니다. 스키마 / 테이블 / 열 데이터 정렬을 변경 .

데이터 정렬이 변경된 후 시각적 쿼리 설명이 없으므로 시각적 쿼리 설명

결론적으로 성능이 중요하고 테이블의 데이터 정렬을 변경할 수있는 경우 옵션 4 로 이동하십시오 . 단일 열에서 작업해야하는 경우 다음과 같이 사용할 수 있습니다.

ALTER TABLE schema1.table1 MODIFY `field` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

귀하의 기여에 감사드립니다. Raffaele, 저는 테이블 1을 캐스팅하지 않고 SP에 전달하기 전에 비교 값을 사용하기 때문에 옵션 1이 인덱스를 사용한다고 생각합니다.
Manatax

지적 해 주셔서 감사합니다. 내 실수 였어 그에 따라 답변을 편집했습니다.
Raffaele

0

이것은 열이 명시 적으로 다른 데이터 정렬로 설정되거나 쿼리 된 테이블에서 기본 데이터 정렬이 다른 경우에 발생합니다.

테이블이 많은 경우이 쿼리를 실행할 때 데이터 정렬을 변경하려는 경우 :

select concat('ALTER TABLE ', t.table_name , ' CONVERT TO CHARACTER 
SET utf8 COLLATE utf8_unicode_ci;') from (SELECT table_name FROM 
information_schema.tables where table_schema='SCHRMA') t;

그러면 열 당 올바른 데이터 정렬을 사용하도록 모든 테이블을 변환하는 데 필요한 쿼리가 출력됩니다.


SP의 기본 데이터 정렬이 쿼리 된 테이블에 사용 된 데이터 정렬과 다른 경우에도 발생합니다.
Manatax
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.