“ ค่าสตริงไม่ถูกต้อง” เมื่อพยายามแทรก UTF-8 ลงใน MySQL ผ่าน JDBC?


228

นี่คือวิธีการตั้งค่าการเชื่อมต่อของฉัน:
Connection conn = DriverManager.getConnection(url + dbName + "?useUnicode=true&characterEncoding=utf-8", userName, password);

และฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อผูกเพื่อเพิ่มแถวลงในตาราง:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...' for column 'content' at row 1

ฉันแทรกหลายพันระเบียนและฉันได้รับข้อผิดพลาดนี้เสมอเมื่อข้อความมี \ xF0 (เช่นค่าสตริงที่ไม่ถูกต้องเริ่มต้นด้วย \ xF0 เสมอ)

การเปรียบเทียบคอลัมน์คือ utf8_general_ci

มีปัญหาอะไร


นั่นคือลาตินเล็กตัวอักษร N กับ TILDE (ñ)
andreszs

สำหรับผู้อื่นพบปัญหานี้คุณสามารถลอง: ในฐานข้อมูล: การเปลี่ยนแปลงฐานข้อมูล database_name ชุดอักขระ CHARACTER utf8mb4 COLLATE utf8mb4_unicode_ci; - มันจะแก้ปัญหา "ต่อจากนี้ไป" สร้างตาราง ไม่ใช่สำหรับตารางที่มีอยู่ สำหรับพวกเขาที่คุณต้องทำ: แก้ไขตาราง table_name แปลงชุดอักขระ utf8mb4 COLLATE utf8mb4_unicode_ci; ที่มา - digitalocean.com/community/questions/...
lingar

คำตอบ:


321

MySQL utf8อนุญาตเฉพาะอักขระ Unicode ที่สามารถแสดงด้วย 3 ไบต์ใน UTF-8 ที่นี่คุณมีตัวละครที่ต้องการ 4 ไบต์: \ xF0 \ x90 \ x8D \ x83 ( U + 10343 ตัวอักษรกรีกแบบอักษร )

ถ้าคุณมี MySQL 5.5 หรือในภายหลังคุณสามารถเปลี่ยนคอลัมน์การเข้ารหัสจากการutf8 utf8mb4การเข้ารหัสนี้อนุญาตให้จัดเก็บอักขระที่มีขนาด 4 ไบต์ใน UTF-8

คุณอาจต้องตั้งค่าคุณสมบัติเซิร์ฟเวอร์character_set_serverเป็นutf8mb4ในไฟล์กำหนดค่า MySQL ดูเหมือนว่าค่าเริ่มต้น Connector / J จะเป็น 3 ไบต์ Unicode เป็นอย่างอื่น :

ตัวอย่างเช่นในการใช้ชุดอักขระ 4 ไบต์ UTF-8 พร้อม Connector / J ให้กำหนดค่าเซิร์ฟเวอร์ MySQL ด้วยcharacter_set_server=utf8mb4และcharacterEncodingไม่ใช้สตริงการเชื่อมต่อ Connector / J ตัวเชื่อมต่อ / J จะตรวจหาการตั้งค่า UTF-8 โดยอัตโนมัติ


151
ช่างเป็นตัวเลือกที่แปลกที่จะมี utf8 จริงๆหมายถึง "ส่วนย่อยของ UTF8 ที่สามารถแสดงเป็น 3 ไบต์"
Eric J.

4
character_encoding_serverไม่ใช่ชื่อตัวแปรกำหนดค่า MySQL ที่ถูกต้อง ฉันพยายามตั้งค่าcharacter_set_serverเป็นutf8mb4แทนนอกเหนือจากแต่ละคอลัมน์ แต่มันไม่ได้เปลี่ยนแปลงอะไรเลย
Romain Paulus

20
# สำหรับแต่ละฐานข้อมูล: แก้ไขฐานข้อมูล database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; # สำหรับแต่ละตาราง: แก้ไขตาราง table_name แปลงเป็นชุดอักขระ utf8mb4 COLLATE utf8mb4_unicode_ci; # สำหรับแต่ละคอลัมน์: แก้ไขตาราง table_name เปลี่ยน column_name column_name VARCHAR (191) ชุดอักขระ CHARACTER utf8mb4 COLLATE utf8mb4_unicode_ci;
iKing

14
แปลกประหลาดที่ UTF-8 ไม่ใช่ UTF-8 จนกว่าจะได้รับการอัปเดตเป็น UTF-8
Klors

3
ดังนั้นคุณแนะนำว่า UTF-8 ที่มี 3 (สาม) ไบต์ไม่สามารถเก็บ LATIN SMALL LETTER N ที่มี TILDE (ñ) และเราต้องการ 4 (สี่) ไบต์ในการสะกด "España" อย่างถูกต้อง? จริงๆ? มันจะมีประโยชน์มากกว่านี้ไหม? เราสามารถเก็บอะไรได้บ้างนอกจาก AZ และ 0-9 ด้วย 3 ไบต์แล้ว ..
andreszs

95

สตริงที่มี\xF0เป็นเพียงอักขระที่เข้ารหัสเป็นหลายไบต์โดยใช้ UTF-8

แม้ว่าการเปรียบเทียบของคุณจะถูกตั้งค่าเป็น utf8_general_ci แต่ฉันสงสัยว่าการเข้ารหัสอักขระของฐานข้อมูลตารางหรือคอลัมน์อาจแตกต่างกัน พวกเขามีการตั้งค่าที่เป็นอิสระ ลอง:

ALTER TABLE database.table MODIFY COLUMN col VARCHAR(255)  
    CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

ทดแทนสิ่งที่ชนิดข้อมูลจริงของคุณสำหรับ VARCHAR (255)


4
พยายามจริง ๆ แล้วไม่ทำงาน ชนิดข้อมูลของคอลัมน์คือ LONGTEXT btw หากเป็นเช่นนี้
Lior

1
แอปของคุณอยู่ในจาวาที่ฉันรับ ลองเรียกใช้ Java ด้วยfile-encodingพารามิเตอร์ที่ระบุ UTF-8 เช่นjava -Dfile.encoding=UTF-8หรือเพิ่มสวิตช์ที่เหมาะสมในไฟล์กำหนดค่า Tomcat (ฯลฯ ) ของคุณ
Eric J.

1
ผมแนะนำให้คุณให้ความสำคัญกับ"การเข้ารหัสอักขระของฐานข้อมูลตารางหรือคอลัมน์อาจจะแตกต่างกัน" นั่นคือสิ่งที่สำคัญที่สุด
Gellie Ann

คุณจะต้องแก้ไขตารางด้วย CHARACTER SET utf8 COLLATE utf8_general_ci จากนั้นหลังจากเปลี่ยนคอลัมน์ CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
Shobhit Sharma

68

มีปัญหาเดียวกันในการบันทึกข้อมูลด้วยutf8mb4ความต้องการเพื่อให้แน่ใจว่า:

  1. character_set_client, character_set_connection, character_set_resultsคือutf8mb4: character_set_clientและcharacter_set_connectionระบุชุดอักขระที่คำสั่งถูกส่งโดยไคลเอนต์, character_set_resultsระบุชุดอักขระที่เซิร์ฟเวอร์ส่งคืนผลลัพธ์แบบสอบถามไปยังไคลเอ็นต์
    ดูcharset การเชื่อมต่อ

  2. การเข้ารหัสตารางและคอลัมน์คือ utf8mb4

สำหรับ JDBC มีสองวิธี:

โซลูชันที่ 1 (ต้องรีสตาร์ท MySQL):

  1. แก้ไขmy.cnfดังต่อไปนี้และเริ่ม MySQL:

    [mysql]
    default-character-set=utf8mb4
    
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    

สิ่งนี้สามารถทำให้แน่ใจว่าฐานข้อมูลและcharacter_set_client, character_set_connection, character_set_resultsเป็นutf8mb4ค่าเริ่มต้น

  1. รีสตาร์ท MySQL

  2. เปลี่ยนการเข้ารหัสตารางและคอลัมน์เป็น utf8mb4

  3. STOP ระบุcharacterEncoding=UTF-8และcharacterSetResults=UTF-8ในช่องเสียบ JDBC ทำให้เกิดนี้จะแทนที่character_set_client, character_set_connection, character_set_resultsไปutf8

โซลูชันที่สอง (ไม่จำเป็นต้องรีสตาร์ท MySQL):

  1. เปลี่ยนการเข้ารหัสตารางและคอลัมน์เป็น utf8mb4

  2. ระบุcharacterEncoding=UTF-8ในช่องเสียบ JDBC สาเหตุเชื่อมต่อ JDBC ไม่ utf8mb4suport

  3. เขียนสถานะ sql ของคุณเช่นนี้ (จำเป็นต้องเพิ่มallowMultiQueries=trueในตัวเชื่อมต่อ jdbc):

    'SET NAMES utf8mb4;INSERT INTO Mytable ...';

นี้จะให้แน่ใจว่าการเชื่อมต่อไปยังเซิร์ฟเวอร์แต่ละมีcharacter_set_client,character_set_connection,character_set_results ดูการเชื่อมต่อ charsetด้วยutf8mb4


3
จุดที่ 3 คือตัวเลือกสำหรับฉันร่วมกับการเปลี่ยน db, ตารางและการเข้ารหัสฟิลด์: 'SET NAMES utf8mb4; INSERT INTO Mytable ... ';
kbbucks

จุดที่ 3 ทำเคล็ดลับสำหรับฉันเช่นกันการเข้ารหัสตารางของฉันตั้งค่าเป็น utf8mb4 แล้ว
Sir_Faenor

การเข้ารหัสตารางเป็นเพียงค่าเริ่มต้น การเปลี่ยนการเข้ารหัสคอลัมน์เป็น utf8mb4 เพียงพอแล้ว
Rick James

วิธีที่สองควรใช้แบบเลือกเช่นไม่เคยถูกนำไปใช้กับSELECTแบบสอบถามเช่นเดียวกับที่set names utf8mb4; select ... from ...จะไม่สร้างResultSetและส่งผลให้เกิดResultSet is from UPDATE. No Data.ข้อผิดพลาดแทน
Bass

โซลูชันที่ 2 เพียงพาร์ 1 ช่วยฉันเมื่อฉันพยายามแทรกข้อความซีริลลิกผ่านแบบฟอร์มการติดต่อของฉัน
Vadim Anisimov

15

ฉันต้องการรวมโพสต์สองสามโพสต์เพื่อให้คำตอบแบบเต็มเนื่องจากดูเหมือนจะเป็นไม่กี่ขั้นตอน

  1. คำแนะนำข้างต้นโดย @madtracey

/etc/mysql/my.cnf หรือ /etc/mysql/mysql.conf.d/mysqld.cnf

[mysql]
default-character-set=utf8mb4

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0

[mysqld]
##
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

อีกครั้งจากคำแนะนำข้างต้นเชื่อมต่อ JDBC ทุกคนcharacterEncoding=UTF-8และcharacterSetResults=UTF-8ลบออกจากพวกเขา

ด้วยชุดนี้-Dfile.encoding=UTF-8ดูเหมือนจะไม่สร้างความแตกต่าง

ฉันยังคงไม่สามารถเขียนข้อความระหว่างประเทศลงในฐานข้อมูลได้รับความล้มเหลวเช่นเดียวกับข้างต้น

ตอนนี้ใช้วิธีการแปลง -a-- ทั้งหมด mysql ฐานข้อมูลตัวอักษรชุดและการเปรียบเทียบเพื่อ utf-8

อัพเดต db ทั้งหมดของคุณเพื่อใช้ utf8mb4

ALTER DATABASE YOURDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

เรียกใช้คิวรีนี้ซึ่งจะให้ข้อมูลที่จำเป็นสำหรับคุณ

SELECT CONCAT(
'ALTER TABLE ',  table_name, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;  ', 
'ALTER TABLE ',  table_name, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;  ')
FROM information_schema.TABLES AS T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` AS C
WHERE C.collation_name = T.table_collation
AND T.table_schema = 'YOURDB'
AND
(C.CHARACTER_SET_NAME != 'utf8mb4'
    OR
 C.COLLATION_NAME not like 'utf8mb4%')

คัดลอกเอาต์พุตวางในตัวแก้ไขแทนที่ทั้งหมด | โดยไม่ต้องโพสต์ใด ๆ กลับสู่ mysql เมื่อเชื่อมต่อกับฐานข้อมูลที่ถูกต้อง

นั่นคือทั้งหมดที่ต้องทำและดูเหมือนว่าทั้งหมดจะทำงานให้ฉัน ไม่ใช่ - Dfile.encoding=UTF-8ไม่ได้เปิดใช้งานและดูเหมือนว่าจะทำงานตามที่คาดไว้

E2A ยังมีปัญหาอยู่ใช่ไหม ฉันอยู่ระหว่างการผลิตอย่างแน่นอนดังนั้นคุณต้องตรวจสอบสิ่งที่ทำโดยข้างต้นเนื่องจากบางครั้งมันไม่ทำงานนี่คือเหตุผลและแก้ไขในสถานการณ์นี้:

show create table user

  `password` varchar(255) CHARACTER SET latin1 NOT NULL,
  `username` varchar(255) CHARACTER SET latin1 NOT NULL,

คุณสามารถเห็นบางส่วนยังคงละตินพยายามที่จะปรับปรุงบันทึกด้วยตนเอง:

ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

ดังนั้นให้แคบลง:

mysql> ALTER TABLE user change username username varchar(255) CHARACTER SET utf8mb4 not NULL;
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
mysql> ALTER TABLE user change username username varchar(100) CHARACTER SET utf8mb4 not NULL;
Query OK, 5 rows affected (0.01 sec)

ในระยะสั้นฉันต้องลดขนาดของเขตข้อมูลนั้นเพื่อให้การอัปเดตทำงานได้

ตอนนี้เมื่อฉันทำงาน:

mysql> ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

มันทำงานได้ทั้งหมด


คำถาม: คำสั่ง ALTER TABLE สุดท้ายจะแปลงเนื้อหาของเขตข้อมูล VARCHAR ทั้งหมดให้เป็นสตริงที่เข้ารหัส UTF8 ของแท้หรือไม่ ฉันถามเพราะฉันมีปัญหาในการแปลงฟิลด์ LATIN1 ของฉันเป็น UTF8 โดยเฉพาะเมื่อพบอักขระñการแปลงล้มเหลวโดยตรงเนื่องจากค่าสตริงไม่ถูกต้อง (ข้อผิดพลาด 1366)
andreszs

ถ้าคุณหมายถึงALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;แปลกพอเมื่อฉันวิ่งนี่เป็นครั้งสุดท้ายที่ทุกสาขาไม่ได้กำหนดชุดอักขระ ดังนั้นรหัสผ่านจากด้านบนจึงกลายเป็นpasswordvarchar (255) ไม่ใช่ NULL (ไม่มีการเข้ารหัส) ซึ่งหมายความว่าคำสั่งสุดท้ายจะต้องทำการค้นหา mysql สิ่งที่คำจำกัดความของตารางเป็นจริงและเพราะตอนนี้ตารางเป็นค่าเริ่มต้นฟิลด์นี้ไม่ต้องการอีกต่อไป - ฉันคิดว่าพวกเขายังคงอยู่กับชุดอักขระเพียงเพราะในระหว่างการถ่ายโอนข้อมูล ไม่สามารถอัปเดตได้และด้วยเหตุนี้จึงเหลืออยู่ในสถานะนั้น
VH

7

ในกรณีของฉันฉันลองทุกอย่างด้านบนไม่มีอะไรทำงาน ฉันค่อนข้างแน่ใจว่าฐานข้อมูลของฉันดูเหมือนด้านล่าง

mysql  Ver 14.14 Distrib 5.7.17, for Linux (x86_64) using  EditLine wrapper

Connection id:      12
Current database:   xxx
Current user:       yo@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.7.17-0ubuntu0.16.04.1 (Ubuntu)
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /var/run/mysqld/mysqld.sock
Uptime:         42 min 49 sec

Threads: 1  Questions: 372  Slow queries: 0  Opens: 166  Flush tables: 1  Open tables: 30  Queries per second avg: 0.144

ดังนั้นฉันจึงค้นหาชุดอักขระคอลัมน์ในทุกตาราง

show create table company;

ปรากฎว่าชุดอักขระคอลัมน์คือละติน นั่นเป็นเหตุผลที่ฉันไม่สามารถแทรกภาษาจีนในฐานข้อมูล

 ALTER TABLE company CONVERT TO CHARACTER SET utf8;

ที่อาจช่วยคุณ :)


7

ฉันมีปัญหาเดียวกันในโครงการราง:

Incorrect string value: '\xF0\xA9\xB8\xBDs ...' for column 'subject' at row1

โซลูชันที่ 1: ก่อนบันทึกเป็น db แปลงสตริงเป็น base64 โดย Base64.encode64(subject) และหลังจากดึงข้อมูลจากการใช้ dbBase64.decode64(subject)

โซลูชันที่ 2:

ขั้นตอนที่ 1: เปลี่ยนชุดอักขระ (และการเรียง) สำหรับคอลัมน์หัวเรื่องโดย

ALTER TABLE t1 MODIFY
subject VARCHAR(255)
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

ขั้นตอนที่ 2: ในการใช้ database.yml

encoding :utf8mb4

4

แค่ทำ

ALTER TABLE `some_table` 
CHARACTER SET = utf8 , COLLATE = utf8_general_ci ;

ALTER TABLE `some_table` 
CHANGE COLUMN `description_with_latin_or_something` `description` TEXT CHARACTER SET 'utf8' NOT NULL ;

ถ้าฉันมีตารางจำนวนมากฉันต้องการเปลี่ยนในฐานข้อมูล และถ้าหากทุกคนมีเอ็นจิ้นการจัดเก็บที่แตกต่างกัน (innodb ฯลฯ )
Yannis Dran

4

สมมติว่าคุณใช้phpmyadminเพื่อแก้ไขข้อผิดพลาดนี้ให้ทำตามขั้นตอนเหล่านี้:

  1. phpMyAdmin
  2. your_table
  3. "แท็บโครงสร้าง"
  4. เปลี่ยน Collation ของฟิลด์ของคุณจากlatin1_swedish_ci(หรืออะไรก็ตาม) เป็นutf8_general_ci

5
ไม่ถูกต้องคุณสมมติว่าเขาใช้ phpMyAdmin
ShaH

ไม่ทำงาน ...... และการเปรียบเทียบจะเปลี่ยนไปใน 'การทำงาน' และไม่อยู่ในโครงสร้าง
Olorunfemi Ajibulu

@OlunfemiAjibulu ใช่คุณสามารถเปลี่ยนได้ใน "โครงสร้าง" เช่นกัน สำหรับบางคนที่นี่ใช้ได้
Teo Mihaila

@TeoMihaila บางทีมันเป็นเวอร์ชัน
Olorunfemi Ajibulu

3

สาเหตุส่วนใหญ่เกิดจากอักขระ Unicode บางตัว ในกรณีของฉันมันเป็นสัญลักษณ์สกุลเงินรูปี

ในการแก้ไขปัญหานี้อย่างรวดเร็วฉันต้องหาตัวละครที่ทำให้เกิดข้อผิดพลาด ฉันคัดลอกข้อความทั้งหมดวางในเท็กซ์เอดิเตอร์เช่น vi และแทนที่อักขระที่หนักใจด้วยข้อความหนึ่ง


3
สหกรณ์กล่าวถึงว่ามีพันระเบียนถูกใส่ ....
Gellie แอน

3

ฉันมีปัญหานี้กับแอปพลิเคชัน PLAY Java ของฉัน นี่คือการติดตามสแต็กของฉันสำหรับข้อยกเว้นนั้น:

javax.persistence.PersistenceException: Error[Incorrect string value: '\xE0\xA6\xAC\xE0\xA6\xBE...' for column 'product_name' at row 1]
  at io.ebean.config.dbplatform.SqlCodeTranslator.translate(SqlCodeTranslator.java:52)
  at io.ebean.config.dbplatform.DatabasePlatform.translate(DatabasePlatform.java:192)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:83)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:49)
  at io.ebeaninternal.server.core.PersistRequestBean.executeInsert(PersistRequestBean.java:1136)
  at io.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:723)
  at io.ebeaninternal.server.core.PersistRequestBean.executeNoBatch(PersistRequestBean.java:778)
  at io.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:769)
  at io.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:456)
  at io.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:406)
  at io.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:393)
  at io.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1602)
  at io.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1594)
  at io.ebean.Model.save(Model.java:190)
  at models.Product.create(Product.java:147)
  at controllers.PushData.xlsupload(PushData.java:67)
  at router.Routes$$anonfun$routes$1.$anonfun$applyOrElse$40(Routes.scala:690)
  at play.core.routing.HandlerInvokerFactory$$anon$3.resultCall(HandlerInvoker.scala:134)
  at play.core.routing.HandlerInvokerFactory$$anon$3.resultCall(HandlerInvoker.scala:133)
  at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$8$$anon$2$$anon$1.invocation(HandlerInvoker.scala:108)
  at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:88)
  at play.http.DefaultActionCreator$1.call(DefaultActionCreator.java:31)
  at play.core.j.JavaAction.$anonfun$apply$8(JavaAction.scala:138)
  at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:655)
  at scala.util.Success.$anonfun$map$1(Try.scala:251)
  at scala.util.Success.map(Try.scala:209)
  at scala.concurrent.Future.$anonfun$map$1(Future.scala:289)
  at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29)
  at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29)
  at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60)
  at scala.concurrent.impl.CallbackRunnable.run(Promise.scala)
  at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:56)
  at play.api.libs.streams.Execution$trampoline$.execute(Execution.scala:70)
  at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:48)
  at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:68)
  at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete(Promise.scala:368)
  at scala.concurrent.impl.Promise$KeptPromise$Kept.onComplete$(Promise.scala:367)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.onComplete(Promise.scala:375)
  at scala.concurrent.impl.Promise.transform(Promise.scala:29)
  at scala.concurrent.impl.Promise.transform$(Promise.scala:27)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.transform(Promise.scala:375)
  at scala.concurrent.Future.map(Future.scala:289)
  at scala.concurrent.Future.map$(Future.scala:289)
  at scala.concurrent.impl.Promise$KeptPromise$Successful.map(Promise.scala:375)
  at scala.concurrent.Future$.apply(Future.scala:655)
  at play.core.j.JavaAction.apply(JavaAction.scala:138)
  at play.api.mvc.Action.$anonfun$apply$2(Action.scala:96)
  at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:304)
  at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:37)
  at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60)
  at scala.concurrent.impl.CallbackRunnable.run(Promise.scala)
  at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
  at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:91)
  at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
  at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:81)
  at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:91)
  at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
  at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:43)
  at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
  at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
  at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
  at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: java.sql.SQLException: Incorrect string value: '\xE0\xA6\xAC\xE0\xA6\xBE...' for column 'product_name' at row 1
  at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
  at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
  at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
  at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
  at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
  at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
  at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
  at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
  at io.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:82)
  at io.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:122)
  at io.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:73)
  ... 59 more

ฉันพยายามบันทึกโดยใช้ io.Ebean ฉันแก้ไขโดยการสร้างฐานข้อมูลของฉันใหม่ด้วยการเปรียบเทียบ utf8mb4 และใช้วิวัฒนาการการเล่นเพื่อสร้างตารางทั้งหมดใหม่เพื่อให้ตารางทั้งหมดควรถูกสร้างใหม่ด้วยการเปรียบเทียบ utf-8

CREATE DATABASE inventory CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

2

ฉันต้องการใช้การเปลี่ยนแปลงเพียงหนึ่งฟิลด์เท่านั้นคุณสามารถลองเป็นอันดับฟิลด์ได้

class MyModel < ActiveRecord::Base
  serialize :content

  attr_accessible :content, :title
end

2

หากคุณกำลังสร้างตาราง MySQL ใหม่คุณสามารถระบุชุดอักขระของคอลัมน์ทั้งหมดเมื่อสร้างและแก้ไขปัญหาให้ฉัน

CREATE TABLE tablename (
<list-of-columns>
)
CHARSET SET utf8mb4 COLLATE utf8mb4_unicode_ci;

คุณสามารถอ่านรายละเอียดเพิ่มเติมได้ที่: https://dev.mysql.com/doc/refman/8.0/th/charset-column.html


2

นี่ไม่ใช่โซลูชันคำแนะนำ .. แต่ควรแบ่งปัน เนื่องจากโครงการของฉันอัพเกรด DBMS จาก Mysql เก่าไปเป็นรุ่นใหม่ล่าสุด (8) แต่ฉันไม่สามารถเปลี่ยนโครงสร้างตารางได้เพียงการกำหนดค่า DBMS (mysql) ทางออกสำหรับเซิร์ฟเวอร์ mysql

ทดสอบบนWindows mysql 8.0.15 ในการค้นหาconfig mysql

SQL โหมด = "....."

uncomment มัน หรือในกรณีของฉันเพียงพิมพ์ / เพิ่ม

SQL โหมด = "NO_ENGINE_SUBSTITUTION"

ทำไมไม่แนะนำวิธีแก้ปัญหา เพราะถ้าคุณใช้ latin1 (กรณีของฉัน) .. ข้อมูลแทรกสำเร็จ แต่ไม่ใช่เนื้อหา (mysql ไม่ตอบสนองด้วยข้อผิดพลาด !!) ตัวอย่างเช่นคุณพิมพ์ข้อมูลเช่นนี้

bla \ x12

มันประหยัด

bla [] (กล่อง)

โอเค .. สำหรับปัญหาของฉัน .. ฉันสามารถเปลี่ยนฟิลด์เป็น UTF8 .. แต่มีปัญหาเล็ก ๆ .. ดูคำตอบข้างต้นเกี่ยวกับวิธีแก้ปัญหาอื่น ๆ ล้มเหลวเพราะคำไม่แทรกเพราะมีมากกว่า 2 ไบต์ (cmiiw) .. นี้ โซลูชันทำให้กล่องข้อมูลการแทรกของคุณกลายเป็น เหตุผลก็คือใช้ blob .. และคุณสามารถข้ามคำตอบของฉันได้

การทดสอบอื่นที่เกี่ยวข้องกับเรื่องนี้คือ .. ใช้utf8_encodeในรหัสของคุณก่อนบันทึก ฉันใช้กับ latin1 และมันก็ประสบความสำเร็จ (ฉันไม่ได้ใช้sql-mode )! เช่นเดียวกับคำตอบข้างต้นโดยใช้base64_encode

คำแนะนำของฉันเพื่อวิเคราะห์ความต้องการตารางของคุณและพยายามเปลี่ยนจากรูปแบบอื่นเป็น UTF8


ใน settings.py ของฉัน (โครงการ Django) ฉันเปลี่ยนเป็น sql-mode = "NO_ENGINE_SUBSTITUTION" มันใช้งานได้ดี
Taciano Morais Silva


1

คุณต้องตั้งค่า utf8mb4 ใน meta html และในเซิร์ฟเวอร์ของคุณจะเปลี่ยน tabel และตั้งค่า collation เป็น utf8mb4


1

คำแนะนำ: ในAWS RDSคุณต้องมีกลุ่มพารามิเตอร์ใหม่สำหรับฐานข้อมูล MySQL ของคุณด้วย params (แทนที่จะแก้ไข my.cnf)

  • collation_connection: utf8mb4_unicode_ci
  • collation_database: utf8mb4_unicode_ci
  • collation_server: utf8mb4_unicode_ci
  • character_set_client: utf8mb4
  • character_set_connection: utf8mb4
  • character_set_database: utf8mb4
  • character_set_results: utf8mb4
  • character_set_server: utf8mb4

หมายเหตุ: character_set_system ยังคง "utf8"

คำสั่ง SQL เหล่านี้ไม่ทำงานอย่างถาวร - เฉพาะในเซสชัน:

set character_set_server = utf8mb4;
set collation_server = utf8mb4_unicode_ci;

0

ฉันยังต้องวางและสร้างโพรซีเดอร์ที่เก็บไว้ของฐานข้อมูล (และฟังก์ชั่นด้วย) อีกครั้งเพื่อให้พวกเขาดำเนินการภายในชุดอักขระใหม่ของ utf8mb4

วิ่ง:

SHOW PROCEDURE STATUS;

…เพื่อดูว่าโพรซีเดอร์ใดไม่ได้รับการอัพเดตเป็นค่า character_set_client, collation_connection ใหม่และการเปรียบเทียบฐานข้อมูล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.