Làm thế nào để sửa lỗi Lỗi không đúng giá trị chuỗi lỗi?


162

Sau khi nhận thấy một ứng dụng có xu hướng loại bỏ các email ngẫu nhiên do lỗi giá trị chuỗi không chính xác, tôi đã đi và chuyển nhiều cột văn bản để sử dụng bộ utf8ký tự cột và cột mặc định đối chiếu ( utf8_general_ci) để nó chấp nhận chúng. Điều này đã sửa hầu hết các lỗi và làm cho ứng dụng ngừng nhận lỗi sql khi nó cũng đánh vào các email không phải là tiếng Latin.

Mặc dù vậy, một số email vẫn khiến chương trình gặp lỗi không đúng giá trị chuỗi: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

Cột nội dung là kiểu MEDIUMTEXTdữ liệu sử dụng bộ utf8ký tự cột và utf8_general_ciđối chiếu cột. Không có cờ nào tôi có thể chuyển đổi trong cột này.

Hãy nhớ rằng tôi không muốn chạm vào hoặc thậm chí nhìn vào mã nguồn ứng dụng trừ khi thực sự cần thiết:

  • Điều gì gây ra lỗi đó? (vâng, tôi biết các email chứa đầy rác ngẫu nhiên, nhưng tôi nghĩ utf8 sẽ khá dễ dãi)
  • Làm thế nào tôi có thể sửa chữa nó?
  • Những ảnh hưởng có thể có của một sửa chữa như vậy là gì?

Một điều tôi đã cân nhắc là chuyển sang một varf utf8 ([một số lượng lớn]) với cờ nhị phân được bật, nhưng tôi không quen với MySQL và không biết liệu cách khắc phục đó có hợp lý không.


3
Hậu họa: Giải pháp của RichieHulum đã giải quyết vấn đề và không đưa ra bất kỳ vấn đề nào khác trong thời gian nó đang chạy. Nó có thể là một chút hack, nhưng nó đã hoạt động và cho phép tôi tránh bị bẩn tay với phần mềm của bên thứ 3 mà tôi không hiểu hết. Tại thời điểm này, chúng tôi đã cập nhật lên phiên bản mới hơn của phần mềm / lược đồ xử lý tất cả các vấn đề mã hóa này một cách chính xác (và đủ mới để nó thực sự được hỗ trợ), khiến cho việc hack không cần thiết.
Brian

Câu trả lời:


43

"\xE4\xC5\xCC\xC9\xD3\xD8"UTF-8 không hợp lệ. Đã kiểm tra bằng Python:

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

Nếu bạn đang tìm cách để tránh các lỗi giải mã trong cơ sở dữ liệu, mã hóa cp1252 (còn gọi là "Windows-1252" hay còn gọi là "Windows Western European") là mã hóa được cho phép nhất - mỗi giá trị byte là một điểm mã hợp lệ.

Tất nhiên, nó sẽ không hiểu UTF-8 chính hãng nữa, cũng như bất kỳ mã hóa không phải cp1252 nào khác, nhưng có vẻ như bạn không quá quan tâm đến điều đó?


4
Chính xác thì ý của bạn là gì, "Tất nhiên là nó sẽ không hiểu UTF-8 chính hãng nữa?"
Brian

5
@Brian: Nếu bạn nói với nó rằng bạn đang cho nó cp1252 và bạn thực sự cho nó UTF-8, giả sử café, nó sẽ hiểu sai như vậy café. Nó sẽ không sụp đổ, nhưng nó sẽ hiểu nhầm các ký tự bit cao.
RichieHulum

3
@Richie: Cơ sở dữ liệu có thể vui vẻ gọi dữ liệu theo bất cứ thứ gì nó muốn, nhưng nếu mã php lấy nó đang nhét nó vào một chuỗi, điều đó sẽ không tạo ra nhiều khác biệt ... phải không? Tôi không thấy chính xác nơi thiếu hiểu biết về UTF-8 có ảnh hưởng.
Brian

7
@Brian: Không, bạn đúng. Ví dụ, thời gian sẽ tạo ra sự khác biệt trong cơ sở dữ liệu, nếu bạn đã sử dụng mệnh đề ORDER BY trong SQL của mình - việc sắp xếp sẽ rất khó khăn khi bạn có các ký tự không phải ASCII.
RichieHulum

11
Vui lòng bỏ đánh dấu câu trả lời này là giải pháp, ẩn một lỗi không phải là giải pháp của bất cứ điều gì. Hủy bỏ đèn quá nóng từ xe của bạn và bạn sẽ thấy.
David Vartanian

133

Tôi sẽ không đề xuất câu trả lời của Richies, vì bạn đang làm hỏng dữ liệu bên trong cơ sở dữ liệu. Bạn sẽ không khắc phục vấn đề của mình nhưng cố gắng "ẩn" nó và không thể thực hiện các hoạt động cơ sở dữ liệu thiết yếu với dữ liệu bị loại bỏ.

Nếu bạn gặp phải lỗi này, dữ liệu bạn đang gửi không được mã hóa UTF-8 hoặc kết nối của bạn không phải là UTF-8. Đầu tiên, xác minh rằng nguồn dữ liệu (một tệp, ...) thực sự là UTF-8.

Sau đó, kiểm tra kết nối cơ sở dữ liệu của bạn, bạn nên làm điều này sau khi kết nối:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Tiếp theo, xác minh rằng các bảng nơi dữ liệu được lưu trữ có bộ ký tự 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`
;

Cuối cùng, hãy kiểm tra cài đặt cơ sở dữ liệu của bạn:

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

Nếu nguồn, vận chuyển và đích là UTF-8, vấn đề của bạn sẽ biến mất;)


1
@Kariem: Điều này thật lạ, bởi vì cài đặt này được bao phủ bởi lệnh SET NAMES, tương đương với việc gọi SET character_set_client, SET character_set_results, SET character_set_connection dev.mysql.com/doc/refman/5.1/en/charset-connection.html
nico gawenda

2
Lệnh thứ hai nên SET CHARACTER SET utf8(không CHARACTER_SET)
Coder

6
Mặc dù câu trả lời này giúp điều tra vấn đề, nhưng nó không trả lời phải làm gì để khắc phục nó. Tôi thấy "latin1" thay vì "utf-8".
Vanuan

2
câu trả lời này rất hay trong việc giải thích vấn đề nhưng rất kém trong việc chi tiết hóa giải pháp (đó là những gì OP yêu cầu). @nicogawenda: Tất cả các truy vấn SQL sẽ được chạy để khắc phục hoàn toàn sự cố là gì? Làm thế nào để sửa tất cả dữ liệu có sẵn?
Clint Eastwood

1
"Nếu nguồn, phương tiện vận chuyển và đích đến là UTF-8, thì vấn đề của bạn đã biến mất;)" đó là mẹo dành cho tôi
suarsITEDger

80

Các loại utf-8 của MySQL không thực sự đúng utf-8 - nó chỉ sử dụng tối đa ba byte cho mỗi ký tự và chỉ hỗ trợ Mặt phẳng đa ngôn ngữ cơ bản (nghĩa là không có Emoji, không có mặt phẳng thiên văn, v.v.).

Nếu bạn cần lưu trữ các giá trị từ các mặt phẳng Unicode cao hơn, bạn cần mã hóa utf8mb4 .


9
Tôi nghĩ rằng đây có thể là sửa chữa tốt nhất. Nâng cấp lên 5.5 và thay thế utf8 bằng utf8mb4 trong các câu trả lời ở trên. Tôi đã chèn dữ liệu utf8 từ Twitter có biểu tượng cảm xúc hoặc ký tự khác cần 4 byte.
rmarscher

Giả sử chúng ta sẽ không nâng cấp lên 5.5. Làm thế nào để chúng tôi ngăn chặn các lỗi?
Người dùng

tôi đã di chuyển quá xa cho câu trả lời hữu ích nhất này
thiết bị cầm tay

1
10 năm kể từ câu hỏi ban đầu. Hãy để biết rằng mã hóa utf8 của MySQL không phải là utf8 thích hợp. Sử dụng utf8mb4! MariaDB cũng vậy. Nếu không, bạn không thể có những giọt nước mắt của niềm vui 😂
Liam

51

Bảng và các trường có mã hóa sai; tuy nhiên, bạn có thể chuyển đổi chúng thành 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;

1
Tôi nghĩ rằng đây là câu trả lời chính xác của tất cả. Tôi có hai bảng có định dạng varf utf8 mỗi bảng. Một trong số đó có lỗi, một cái khác là tốt. ngay cả người dùng tôi 'cập nhật chọn' tạo một bản sao từ cột 'tốt' utf8 sang một bảng khác, cũng xảy ra lỗi tương tự. Đó là bởi vì hai bảng được tạo trong các phiên bản khác nhau của MySQL.
AiShiguang

Đúng! Đó là cấu hình sai từ bảng cơ sở dữ liệu của tôi quá. Tôi nghĩ rằng câu trả lời này phải là câu trả lời đúng. Vấn đề của tôi là đối chiếu được chọn là utf8_unicode_ci thay vì utf8_general_ci. Cảm ơn :)
jprivillaso

2
Câu trả lời này đang làm gì ở đây, nên ở trên cùng
Sagun Shrestha

1
Điều này giúp, nó cho bạn biết những gì cần cố gắng, thay vì những gì có thể sai.
Victor Di

Cảm ơn bạn! Nó chỉ giúp tôi rất nhiều Tôi đã thay đổi kiến ​​đối chiếu bảng Tôi nghĩ rằng nó nên như vậy nhưng các trường vẫn là đối chiếu ascii ...
Radu

25

Tôi đã giải quyết vấn đề này ngày hôm nay bằng cách thay đổi cột thành loại 'LONGBLOB', nơi lưu trữ các byte thô thay vì các ký tự UTF-8.

Nhược điểm duy nhất của việc này là bạn phải tự chăm sóc mã hóa. Nếu một khách hàng trong ứng dụng của bạn sử dụng mã hóa UTF-8 và một khách hàng khác sử dụng CP1252, bạn có thể gửi email với các ký tự không chính xác. Để tránh điều này, luôn luôn sử dụng cùng một mã hóa (ví dụ UTF-8) trên tất cả các ứng dụng của bạn .

Tham khảo trang này http://dev.mysql.com/doc/refman/5.0/en/blob.html để biết thêm chi tiết về sự khác biệt giữa TEXT / LONGTEXT và BLOB / LONGBLOB. Ngoài ra còn có nhiều tranh luận khác trên web thảo luận về hai điều này.


1
Giải pháp này có vẻ là cách dễ nhất để đi. Tôi đã thử vài mã hóa khác mà không thành công.
Simeon Abolarinwa

10

Trước tiên hãy kiểm tra xem default_character_set_name của bạn có phải là utf8 không.

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

Nếu kết quả không phải là utf8, bạn phải chuyển đổi cơ sở dữ liệu của mình. Đầu tiên bạn phải lưu một bãi rác.

Để thay đổi mã hóa bộ ký tự thành UTF-8 cho tất cả các bảng trong cơ sở dữ liệu đã chỉ định, hãy nhập lệnh sau vào dòng lệnh. Thay thế DBNAME bằng tên cơ sở dữ liệu:

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

Để thay đổi mã hóa bộ ký tự thành UTF-8 cho chính cơ sở dữ liệu, hãy nhập lệnh sau tại dấu nhắc mysql >. Thay thế DBNAME bằng tên cơ sở dữ liệu:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Bây giờ bạn có thể thử lại để viết ký tự utf8 vào cơ sở dữ liệu của bạn. Giải pháp này giúp tôi khi tôi cố tải lên 200000 hàng tệp csv vào cơ sở dữ liệu của mình.


8

Nói chung, điều này xảy ra khi bạn chèn chuỗi vào các cột có mã hóa / đối chiếu không tương thích.

Tôi đã gặp lỗi này khi tôi có TRIGGER, do kế thừa đối chiếu của máy chủ vì một số lý do. Và mặc định của mysql là (ít nhất là trên Ubuntu) latin-1 với đối chiếu Thụy Điển. Mặc dù tôi đã có cơ sở dữ liệu và tất cả các bảng được đặt thành UTF-8, tôi vẫn chưa đặt my.cnf:

/etc/mysql/my.cnf:

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

Và điều này phải liệt kê tất cả các kích hoạt với utf8- *:

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

Và một số biến được liệt kê bởi điều này cũng nên có utf-8- * (không có Latin-1 hoặc mã hóa khác):

show variables like 'char%';

6

Mặc dù đối chiếu của bạn được đặt thành utf8_general_ci, tôi nghi ngờ rằng mã hóa ký tự của cơ sở dữ liệu, bảng hoặc cột thậm chí có thể khác nhau.

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

5

Tôi đã có một lỗi tương tự ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). Tôi đã cố gắng thay đổi bộ ký tự của cột thành utf8mb4và sau đó lỗi đã thay đổi thành 'Data too long for column 'content' at row 1'.
Hóa ra mysql chỉ cho tôi lỗi sai. Tôi quay lại bộ ký tự của cột thành utf8và thay đổi loại cột thành MEDIUMTEXT. Sau đó, lỗi biến mất.
Tôi hi vọng nó giúp ích cho ai đó.
Nhân tiện, MariaDB trong cùng một trường hợp (tôi đã kiểm tra cùng một INSERT ở đó) chỉ cần cắt một văn bản mà không gặp lỗi.


MySQL cũng vậy, tôi mệt mỏi rất nhiều thứ, nhận ra mysql không hỗ trợ giải mã 4 byte utf-8 ở phiên bản này và đang cố gắng tìm hiểu điều gì gây ra điều này. Thay đổi loại rõ ràng là câu trả lời, một giải pháp ngay lập tức.
Liza

4

Lỗi đó có nghĩa là bạn có chuỗi có mã hóa không chính xác (ví dụ: bạn đang cố nhập chuỗi được mã hóa ISO-8859-1 vào cột được mã hóa UTF-8) hoặc cột không hỗ trợ dữ liệu bạn đang cố nhập.

Trong thực tế, vấn đề thứ hai là do triển khai MySQL UTF-8 chỉ hỗ trợ các ký tự UNICODE cần 1-3 byte khi được trình bày trong UTF-8. Xem "Giá trị chuỗi không chính xác" khi cố gắng chèn UTF-8 vào MySQL thông qua JDBC? để biết chi tiết.


2

Giải pháp cho tôi khi chạy vào giá trị chuỗi Không chính xác này: '\ xF8' cho lỗi cột sử dụng scriptcase là đảm bảo rằng cơ sở dữ liệu của tôi được thiết lập cho chung chung utf8 và các trường hợp đối chiếu của tôi cũng vậy. Sau đó, khi tôi thực hiện nhập dữ liệu của mình vào tệp csv, tôi tải csv vào UE Studio sau đó lưu tệp được định dạng là utf8 và Voila! Nó hoạt động như một lá bùa, 29000 hồ sơ trong đó không có lỗi. Trước đây tôi đã cố gắng nhập một excel tạo csv.


2

Tôi đã thử tất cả các giải pháp trên (tất cả đều mang lại điểm hợp lệ), nhưng không có gì hiệu quả với tôi.

Cho đến khi tôi thấy rằng ánh xạ trường bảng MySQL của tôi trong C # đang sử dụng một loại không chính xác: MySqlDbType.Blob . Tôi đã thay đổi nó thành MySqlDbType.Text và bây giờ tôi có thể viết tất cả các ký hiệu UTF8 mà tôi muốn!

ps Trường bảng MySQL của tôi thuộc loại "LongText". Tuy nhiên, khi tôi tự động tạo ánh xạ trường bằng phần mềm MyGeneration, nó sẽ tự động đặt loại trường là MySqlDbType.Blob trong C #.

Thật thú vị, tôi đã sử dụng loại MySqlDbType.Blob với các ký tự UTF8 trong nhiều tháng mà không gặp khó khăn gì, cho đến một ngày tôi đã thử viết một chuỗi với một số ký tự cụ thể trong đó.

Hy vọng điều này sẽ giúp một người đang đấu tranh để tìm ra lý do cho lỗi này.


1

Tôi đã thêm nhị phân trước tên cột và giải quyết lỗi bộ ký tự.

chèn vào các giá trị bảngA (chuỗi ký tự nhị phân1);


1

Xin chào, tôi cũng gặp lỗi này khi sử dụng cơ sở dữ liệu trực tuyến của mình từ máy chủ godaddy, tôi nghĩ rằng nó có phiên bản mysql từ 5.1 trở lên. nhưng khi tôi làm từ máy chủ localhost của tôi (phiên bản 5.7) thì tôi đã tạo được bảng từ máy chủ cục bộ và sao chép vào máy chủ trực tuyến bằng cách sử dụng mysql. Tôi nghĩ rằng vấn đề là do bộ ký tự

Ảnh chụp màn hình ở đây


1

Để khắc phục lỗi này, tôi đã nâng cấp cơ sở dữ liệu MySQL của mình lên utf8mb4, hỗ trợ bộ ký tự Unicode đầy đủ bằng cách làm theo hướng dẫn chi tiết này . Tôi khuyên bạn nên xem qua nó một cách cẩn thận, vì có khá nhiều gotchas (ví dụ: các khóa chỉ mục có thể trở nên quá lớn do các mã hóa mới mà sau đó bạn phải sửa đổi các loại trường).


1

Có câu trả lời tốt ở đây. Tôi chỉ thêm tôi vì tôi gặp phải lỗi tương tự nhưng hóa ra đó là một vấn đề hoàn toàn khác. (Có thể trên bề mặt giống nhau, nhưng một nguyên nhân gốc rễ khác.)

Đối với tôi, lỗi xảy ra cho trường sau:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
private URI consulUri;

Điều này cuối cùng được lưu trữ trong cơ sở dữ liệu như là một tuần tự nhị phân của URIlớp. Điều này đã không tăng bất kỳ cờ nào với thử nghiệm đơn vị (sử dụng H2) hoặc thử nghiệm tích hợp / CI (sử dụng MariaDB4j ), nó đã xuất hiện trong thiết lập giống như sản xuất của chúng tôi. (Mặc dù, khi đã hiểu được vấn đề, thật dễ dàng để thấy giá trị sai trong ví dụ MariaDB4j; nó không làm nổ tung bài kiểm tra.) Giải pháp là xây dựng một trình ánh xạ loại tùy chỉnh:

package redacted;

import javax.persistence.AttributeConverter;
import java.net.URI;
import java.net.URISyntaxException;

import static java.lang.String.format;

public class UriConverter implements AttributeConverter<URI, String> {
    @Override
    public String convertToDatabaseColumn(URI attribute) {
        return attribute.toString();
    }

    @Override
    public URI convertToEntityAttribute(String field) {
        try {
            return new URI(field);
        }
        catch (URISyntaxException e) {
            throw new RuntimeException(format("could not convert database field to URI: %s", field));
        }
    }
}

Được sử dụng như sau:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
@Convert(converter = UriConverter.class)
private URI consulUri;

Theo như Hibernate có liên quan, có vẻ như nó có một loạt các người lập bản đồ loại được cung cấp , bao gồm cho java.net.URL, nhưng không cho java.net.URI(đó là những gì chúng ta cần ở đây).


1

Nếu bạn tình cờ xử lý giá trị với một số hàm chuỗi trước khi lưu, hãy đảm bảo rằng hàm có thể xử lý đúng các ký tự đa dòng. Các hàm chuỗi không thể làm điều đó và, giả sử, cố gắng cắt bớt có thể phân tách một trong các ký tự đa chuỗi đơn ở giữa và điều đó có thể gây ra các tình huống lỗi chuỗi như vậy.

Trong PHP chẳng hạn, bạn sẽ cần phải chuyển từ substrsang mb_substr.


0

Trong trường hợp của tôi, đầu tiên tôi đã gặp một '???' trong trang web của tôi, sau đó tôi kiểm tra bộ ký tự của Mysql là tiếng Latin, vì vậy tôi đổi nó thành utf-8, sau đó tôi khởi động lại dự án của mình, sau đó tôi gặp lỗi tương tự với bạn, sau đó tôi thấy rằng tôi quên thay đổi bộ ký tự của cơ sở dữ liệu và thay đổi thành utf-8, boom, nó đã hoạt động.


0

Tôi đã thử hầu hết các bước được đề cập ở đây. Không có làm việc. Đã tải xuống mariadb. Nó đã làm việc. Tôi biết đây không phải là một giải pháp nhưng điều này có thể giúp ai đó nhanh chóng xác định vấn đề hoặc đưa ra giải pháp tạm thời.

Server version: 10.2.10-MariaDB - MariaDB Server
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)

0

Trong trường hợp của tôi, vấn đề đó đã được giải quyết bằng cách thay đổi mã hóa cột Mysql thành 'binary' (kiểu dữ liệu sẽ được tự động thay đổi thành VARBINARY). Có lẽ tôi sẽ không thể lọc hoặc tìm kiếm với cột đó, nhưng tôi không cần điều đó.



-2

1 - Bạn phải khai báo trong kết nối của mình bản sửa lỗi UTF8. http://php.net/manual/en/mysqli.set-charset.php .

2 - Nếu bạn đang sử dụng dòng lệnh mysql để thực thi tập lệnh, bạn phải sử dụng cờ, như: Cmd: C:\wamp64\bin\mysql\mysql5.7.14\bin\mysql.exe -h localhost -u root -P 3306 --default-character-set=utf8 omega_empresa_parametros_336 < C:\wamp64\www\PontoEletronico\PE10002Corporacao\BancoDeDadosModelo\omega_empresa_parametros.sql

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.