MySQL
ทำไมข้อความภาษาไทยจึงเพี้ยนเป็นเครื่องหมายแปลกๆ?
ข้อความภาษาไทยเพี้ยนเป็น "?", "???", "□□□" หรือตัวอักษรแปลก ๆ อื่น ๆ เกิดจาก "Character Set" ที่ฐานข้อมูล (Database) ใช้ไม่ถูกต้อง Character Set คือการสอบเทียม (Encoding) ที่บอกว่า "ตัวอักษรนี้ ควรแสดงผลอย่างไร"
ตัวอย่างปัญหา:
- Database ถูกสร้างด้วย Character Set "latin1" (สำหรับภาษาละติน) แต่เก็บข้อความภาษาไทย (unicode) → ตัวอักษรไม่ตรงกัน
- ข้อมูลถูกเก็บด้วย UTF-8 แต่ไฟล์ Connection ใช้ Latin1 → ผลลัพธ์เพี้ยน
- ข้อมูลเก่าใช้ "utf8" (เวอร์ชันเก่า MySQL ที่เก็บได้ 3 Bytes เท่านั้น) แต่ "emoji" ต้องการ 4 Bytes → emoji เพี้ยนหรือหายไป
Character Set ทั่วไปใน MySQL
Character Set ที่ใช้บ่อย:
- latin1 — สำหรับภาษาละติน อังกฤษ ฝรั่งเศส เยอรมัน (ไม่รองรับภาษาไทย)
- utf8 — เวอร์ชันเก่า MySQL ที่เก็บ 3 Bytes สูงสุด ไม่รองรับ Emoji 4 Bytes
- utf8mb4 — เวอร์ชันสมบูรณ์ 4 Bytes รองรับ Emoji, ภาษาไทย, ภาษาจีน, ญี่ปุ่น ทุกภาษา (ควรใช้นี้)
- binary — เก็บข้อมูลเป็น Binary ไม่มีการแปลง (ไม่ใช้เว้นแต่งานพิเศษ)
การโต้ตอบ (Collation) เป็นส่วนอีกอย่างหนึ่ง Collation บอกว่า "ตัวอักษรไหนควร Sorted ไว้ก่อนหลัง" เช่น utf8mb4_unicode_ci หมายถึง UTF8MB4 Character Set กับ Unicode Collation ที่ Case-Insensitive (ไม่แยกแยะตัวพิมพ์ใหญ่เล็ก)
วิธีแก้: เปลี่ยนจาก Latin1 เป็น UTF8MB4
วิธีแก้ใน phpMyAdmin (ที่ง่ายที่สุด):
- Login phpMyAdmin ผ่าน cPanel
- เลือก Database ที่ต้องการแก้
- ไปยัง Tab Operations
- หา Collation และเปลี่ยนเป็น utf8mb4_unicode_ci หรือ utf8mb4_general_ci
- คลิก Go หรือ Apply
ขั้นตอนหลังจากนั้น เปลี่ยน Character Set ของแต่ละ Table:
- ในแถบด้านซ้าย เลือก Table (เช่น wp_posts)
- ไปยัง Tab Operations
- หา Collation และเปลี่ยนเป็น utf8mb4_unicode_ci
- คลิก Go
- ทำซ้ำสำหรับทุก Table ใน Database
ดำเนินการเปลี่ยน Character Set ของแต่ละ Column
นอกจากการเปลี่ยน Database และ Table แล้ว ควรเปลี่ยน Column เดี่ยว ๆ (Text Field) ให้เป็น UTF8MB4 ด้วย
ใน phpMyAdmin GUI
- เลือก Table ที่ต้องการแก้
- ไปยัง Tab Structure
- ดู Column ที่เป็น VARCHAR, TEXT, LONGTEXT เป็นต้น (Text Field)
- คลิก "Change" ไอคอนสำหรับ Column นั้น
- ค้นหา Collation แล้วเปลี่ยนเป็น utf8mb4_unicode_ci
- คลิก Go หรือ Save
- ทำซ้ำสำหรับทุก Text Column
ใช้ SQL Command (สำหรับผู้ช่วย)
-- 1. เปลี่ยน Character Set ของ Database ทั้งหมด
ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 2. เปลี่ยน Character Set ของ Table
ALTER TABLE table_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 3. เปลี่ยน Character Set ของ Column เดี่ยว
ALTER TABLE table_name MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 4. เปลี่ยนทั้ง Table โดย Loop ผ่าน phpMyAdmin
-- หากต้องเปลี่ยนทีเดียวหลาย Table ใช้ SQL นี้ (ต้องใช้ root user):
SELECT CONCAT('ALTER TABLE ',TABLE_NAME,' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='database_name';
-- จากนั้น Copy ผลลัพธ์แล้วรัน SQL ต่อเนื่อง
ตั้งค่า Connection Character Set ให้ Web Application
นอกจากตั้งค่า Database แล้ว ต้องบอก Application (WordPress, PHP, เป็นต้น) ให้ใช้ UTF-8 Character Set เมื่อติดต่อ MySQL
สำหรับ WordPress ใน wp-config.php
// ตรวจหาบรรทัดนี้ใน wp-config.php แล้วทำให้เป็นแบบนี้:
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', 'utf8mb4_unicode_ci');
// ถ้าไม่มี ให้เพิ่มบรรทัดเหล่านี้ก่อน "That's all, stop editing!":
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', 'utf8mb4_unicode_ci');
สำหรับ PHP Custom Script
// สำหรับ MySQLi
$conn = new mysqli("localhost", "username", "password", "database");
$conn->set_charset("utf8mb4");
// สำหรับ PDO
$dsn = 'mysql:host=localhost;dbname=database;charset=utf8mb4';
$pdo = new PDO($dsn, 'username', 'password');
ใน .htaccess สำหรับ Apache
AddDefaultCharset utf-8
php_value default_charset utf-8
ตรวจสอบว่า Character Set ถูกเปลี่ยนเรียบร้อย
หลังจากเปลี่ยนแล้ว ตรวจสอบด้วยคำสั่ง SQL นี้:
-- 1. ตรวจสอบ Character Set ของ Database
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME='database_name';
-- ควรแสดง utf8mb4 และ utf8mb4_unicode_ci
-- 2. ตรวจสอบ Character Set ของ Table
SHOW CREATE TABLE table_name;
-- ตรวจหาบรรทัด "CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
-- 3. ตรวจสอบ Character Set ของแต่ละ Column
SHOW FULL COLUMNS FROM table_name;
-- ตรวจสอบ Column "Collation" ควรเป็น utf8mb4_unicode_ci
แก้ปัญหาที่พบบ่อย
Error: "เปลี่ยน Character Set แล้ว ตัวอักษรเก่ายังเพี้ยน"
เกิดเมื่อข้อมูลเก่า (ที่เก็บไว้ด้วย Latin1) ถูก Convert ผิด Character Set ไม่สามารถ "แปล" กลับเป็นตัวอักษรปกติได้
วิธีแก้: ต้อง Restore จาก Backup ที่ยังดี หรือ Export ข้อมูลออกมาเป็น CSV แล้วลบข้อมูลเก่า ใส่ข้อมูลใหม่ด้วย UTF-8 ถูกต้อง (วิธีนี้ยุ่งยาก) หรือลองใช้ Tool MySQL Converter ที่บุคคลที่สาม เช่น iconv หรือ Mysqldump --default-character-set=utf8mb4 แต่ก่อนเริ่มต้อง Backup ให้ปลอดภัยก่อน
Error: "ข้อมูล Emoji หรือตัวอักษรพิเศษหายไปหลังเปลี่ยน Character Set"
เกิดเมื่อใช้ utf8 (3 bytes) เก่า ลองแบบมี emoji (4 bytes) Conversion อาจทำให้ emoji หายไป
วิธีแก้: ต้อง Restore ข้อมูล Emoji ใหม่ เพราะข้อมูล Emoji ที่เก็บใน utf8 เก่า ตัวอักษรแล้วจึง Recover ไม่ได้ อนาคตหลังนี้เก็บใช้ utf8mb4 ให้ถูกต้อง
Error: "หลังเปลี่ยน Character Set WordPress ยังแสดงตัวอักษรไทยเพี้ยน"
อาจเกิดจากเบราว์เซอร์ Cache หรือ WordPress Cache ยังเก็บข้อมูลเก่าไว้
วิธีแก้: ล้าง WordPress Cache (ผ่าน W3 Total Cache Plugin หรือ Clear Cache ด้วยมือ) ล้าง Browser Cache (Ctrl+Shift+Delete) จากนั้น Refresh หน้าเว็บใหม่
Error: "ไม่สามารถทำ ALTER TABLE ได้ เพราะเกิด MySQL Error"
อาจเกิดจากไม่มี Free Disk Space หรือ Table กำลังถูกใช้ หรือ Hosting จำกัดการใช้ ALTER TABLE
วิธีแก้: ลองกำหนดเวลา ALTER ในช่วง Maintenance (ที่ Traffic น้อยที่สุด) หรือติดต่อ Hosting Provider ขอให้ยกเลิก Limit ALTER TABLE ชั่วคราว
Error: "หลังทำ utf8mb4 Emoji แสดงผลเป็น □ หรือหายไปเลย"
อาจเกิดจากเว็บเบราว์เซอร์ไม่รองรับ Emoji Font หรือ CSS ไม่ได้กำหนด Font ที่รองรับ Emoji
วิธีแก้: ตรวจสอบ HTML Head ของเว็บว่ามีบรรทัด `` หรือไม่ และลองเพิ่ม Emoji Font ให้กับ CSS เช่น `font-family: 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif;` ลองใช้เบราว์เซอร์อื่น เช่น Chrome หรือ Firefox เพื่อตรวจสอบว่า Emoji ถูกแสดงผลได้จริงหรือไม่
คำถามที่พบบ่อย
Q: utf8 กับ utf8mb4 มีความต่างกันตรงไหน?
A: utf8 ในภาษาทั่วไป (Unicode) รองรับ 4 Bytes แต่ MySQL utf8 เก่า (created ก่อน version 5.5.3) เก็บได้ 3 Bytes สูงสุด ดังนั้นไม่รองรับ Emoji หรืออักษร Rare ที่ต้อง 4 Bytes ในขณะที่ utf8mb4 ในทั้ง MySQL รองรับ 4 Bytes เต็มตัว ควรใช้ utf8mb4 เสมอ
Q: ต้องเปลี่ยน Character Set ทั้ง Database หรือแค่ Table ที่เก็บภาษาไทย?
A: ควรเปลี่ยนทั้ง Database และทุก Table เพื่อให้เกิด Consistency ถ้าสร้าง Table ใหม่ในภายหลัง มันจะ Inherit Character Set จาก Database โดยอัตโนมัติ
Q: เปลี่ยน Character Set แล้ว Storage ของ Database จะเพิ่มขึ้นหรือ?
A: ไม่มากนัก utf8mb4 ใช้ 4 Bytes ต่อตัวอักษร แต่ Database ส่วนใหญ่เก็บ ASCII (ตัวอักษรอังกฤษ) ที่ใช้ 1 Byte เท่านั้น ดังนั้นการเปลี่ยนเป็น utf8mb4 จะเพิ่ม Storage เพียง 5-10% ที่สูงสุด (ขึ้นอยู่กับปริมาณข้อความภาษาไทย)
อยากรู้ว่าการตั้งค่าโดเมนหรือ DNS ของคุณถูกต้องหรือไม่ ลองตรวจสอบฟรีได้ที่ dnsxray.com เครื่องมือวิเคราะห์สุขภาพโดเมนที่ใช้งานง่าย