[mysql] “잘못된 문자열 값”오류를 수정하는 방법?

잘못된 문자열 값 오류로 인해 응용 프로그램이 임의의 전자 메일을 삭제하는 경향이 있음을 알았지 만 많은 문자 열을 utf8열 문자 세트와 기본 열 콜 레이션 ( utf8_general_ci) 을 사용하도록 전환 하여 허용했습니다. 이로 인해 대부분의 오류가 해결되었으며 비 라틴 전자 메일에 부딪히면 응용 프로그램에서 SQL 오류가 발생하지 않습니다.

그럼에도 불구하고 일부 이메일은 여전히 ​​프로그램이 잘못된 문자열 값 errrors에 도달하도록합니다. (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

내용 열은 열 문자 MEDIUMTEXT집합과 열 조합을 사용 하는 데이터 형식입니다 . 이 열에서 토글 할 수있는 플래그가 없습니다.utf8utf8_general_ci

절대적으로 필요한 경우가 아니면 응용 프로그램 소스 코드를 만지거나 보지 않으려는 것을 명심하십시오.

  • 그 오류의 원인은 무엇입니까? (예, 이메일에 임의의 쓰레기가 가득 차 있다는 것을 알고 있지만 utf8은 꽤 관대하다고 생각했습니다)
  • 어떻게 고칠 수 있습니까?
  • 그러한 수정의 영향은 무엇입니까?

내가 생각한 것 중 하나는 바이너리 플래그를 켜고 utf8 varchar ([일부 큰 숫자])로 바꾸는 것이지만 MySQL에 익숙하지 않으며 그러한 수정이 의미가 있는지 전혀 모른다.



답변

"\xE4\xC5\xCC\xC9\xD3\xD8"유효한 UTF-8이 아닙니다. 파이썬을 사용하여 테스트 :

>>> "\xE4\xC5\xCC\xC9\xD3\xD8".decode("utf-8")
...
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data

데이터베이스 내에서 디코딩 오류를 피하는 방법을 찾고 있다면 cp1252 인코딩 (일명 “Windows-1252”, “Windows Western European”)이 가장 허용되는 인코딩입니다. 모든 바이트 값은 유효한 코드 포인트입니다.

물론 더 이상 진짜 UTF-8이나 다른 비 CP1252 인코딩을 이해하지 못하지만 너무 걱정하지 않는 것처럼 들립니까?


답변

데이터베이스 내부의 데이터를 망쳐 놓고 있기 때문에 Richies의 대답을 제안하지 않습니다. 문제점을 수정하지는 않지만 문제점을 “숨기려고”하고 랩된 데이터로 필수 데이터베이스 조작을 수행 할 수 없습니다.

이 오류가 발생하면 전송중인 데이터가 UTF-8로 인코딩되지 않았거나 연결이 UTF-8이 아닙니다. 먼저 데이터 소스 (파일, …)가 실제로 UTF-8인지 확인하십시오.

그런 다음 데이터베이스 연결을 확인하십시오. 연결 한 후에이 작업을 수행해야합니다.

SET NAMES 'utf8';
SET CHARACTER SET utf8;

다음으로, 데이터가 저장된 테이블에 utf8 문자 세트가 있는지 확인하십시오.

SELECT
  `tables`.`TABLE_NAME`,
  `collations`.`character_set_name`
FROM
  `information_schema`.`TABLES` AS `tables`,
  `information_schema`.`COLLATION_CHARACTER_SET_APPLICABILITY` AS `collations`
WHERE
  `tables`.`table_schema` = DATABASE()
  AND `collations`.`collation_name` = `tables`.`table_collation`
;

마지막으로 데이터베이스 설정을 확인하십시오.

mysql> show variables like '%colla%';
mysql> show variables like '%charac%';

소스, 전송 및 대상이 UTF-8이면 문제가 해결 된 것입니다.)


답변

MySQL의 utf-8 유형은 실제로 적절한 utf-8이 아닙니다. 문자 당 최대 3 바이트 만 사용하며 기본 다국어 평면 (이모 지, 아스트랄 평면 등) 만 지원합니다.

더 높은 유니 코드 평면의 값을 저장해야하는 경우 utf8mb4 인코딩 이 필요합니다 .


답변

테이블과 필드의 인코딩이 잘못되었습니다. 그러나 UTF-8로 변환 할 수 있습니다.

ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest CHANGE title title VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci;


답변

오늘 UTF-8 문자 대신 원시 바이트를 저장하는 ‘LONGBLOB’유형으로 열을 변경 하여이 문제를 해결했습니다.

이 작업의 유일한 단점은 인코딩을 직접 관리해야한다는 것입니다. 응용 프로그램의 한 클라이언트가 UTF-8 인코딩을 사용하고 다른 클라이언트가 CP1252를 사용하는 경우 전자 메일이 잘못된 문자로 전송 될 수 있습니다. 이를 피하려면 모든 애플리케이션 에서 항상 동일한 인코딩 (예 : UTF-8)을 사용하십시오 .

TEXT / LONGTEXT와 BLOB / LONGBLOB의 차이점에 대한 자세한 내용은 이 페이지 http://dev.mysql.com/doc/refman/5.0/en/blob.html 을 참조하십시오. 웹에서이 두 가지를 논의하는 다른 주장들도 많이 있습니다.


답변

먼저 default_character_set_name이 utf8인지 확인하십시오.

SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";

결과가 utf8이 아닌 경우 데이터베이스를 변환해야합니다. 처음에는 덤프를 저장해야합니다.

지정된 데이터베이스의 모든 테이블에 대해 문자 세트 인코딩을 UTF-8로 변경하려면 명령 행에 다음 명령을 입력하십시오. DBNAME을 데이터베이스 이름으로 바꾸십시오.

mysql --database=DBNAME -B -N -e "SHOW TABLES" | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' | mysql --database=DBNAME

데이터베이스 자체에서 문자 세트 인코딩을 UTF-8로 변경하려면 mysql > 프롬프트 에서 다음 명령을 입력하십시오 . DBNAME을 데이터베이스 이름으로 바꾸십시오.

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

이제 데이터베이스에 utf8 문자를 쓰려고 다시 시도 할 수 있습니다. 이 솔루션은 데이터베이스에 200000 행의 CSV 파일을 업로드하려고 할 때 도움이됩니다.


답변

일반적으로 인코딩 / 콜 레이션이 호환되지 않는 열에 문자열을 삽입 할 때 발생합니다.

TRIGGER가있을 때이 오류가 발생하여 어떤 이유로 서버의 데이터 정렬을 상속합니다. 그리고 mysql의 기본값은 스웨덴어 데이터 정렬이있는 (적어도 우분투에서는) latin-1입니다. 데이터베이스와 모든 테이블을 UTF-8로 설정했지만 아직 설정하지 않았습니다 my.cnf.

/etc/mysql/my.cnf :

[mysqld]
character-set-server=utf8
default-character-set=utf8

그리고 이것은 모든 트리거를 utf8- *로 나열해야합니다.

select TRIGGER_SCHEMA, TRIGGER_NAME, CHARACTER_SET_CLIENT, COLLATION_CONNECTION, DATABASE_COLLATION from information_schema.TRIGGERS

그리고 여기에 나열된 변수 중 일부에는 utf-8- *가 있어야합니다 (라틴어 -1 또는 다른 인코딩 없음).

show variables like 'char%';