พฤติกรรม Implicit Cast ของ MySQL ใน WHERE clause
เมื่อเปรียบเทียบคอลัมน์ VARCHAR กับตัวเลข MySQL จะพยายามแปลงสตริงเป็นตัวเลขอัตโนมัติ โดยอ่านตัวเลขนำหน้า (leading digits) จนกว่าจะเจอตัวอักษรที่ไม่ใช่ตัวเลข
สร้างตารางและข้อมูล
mysql> create table DemoTable1390 (
-> StudentId varchar(20)
-> );
Query OK, 0 rows affected (0.93 sec)
mysql> insert into DemoTable1390 values('563_John');
mysql> insert into DemoTable1390 values('1001_Carol_Taylor');
mysql> insert into DemoTable1390 values('David_Miller_789');
mysql> insert into DemoTable1390 values('456_AdamSmith');
ข้อมูลทั้งหมด
+-------------------+ | StudentId | +-------------------+ | 563_John | | 1001_Carol_Taylor | | David_Miller_789 | | 456_AdamSmith | +-------------------+
คำสั่ง WHERE ด้วยตัวเลข (Implicit Cast)
mysql> select * from DemoTable1390 where StudentId = 456;
ผลลัพธ์
+---------------+ | StudentId | +---------------+ | 456_AdamSmith | +---------------+ 1 row in set, 4 warnings (0.02 sec)
อธิบายพฤติกรรม
'456_AdamSmith'→ อ่านตัวเลขนำหน้าได้456→ ตรงเงื่อนไข'563_John'→ แปลงเป็น563→ ไม่ตรง'1001_Carol_Taylor'→ แปลงเป็น1001→ ไม่ตรง'David_Miller_789'→ เริ่มด้วยตัวอักษร → แปลงเป็น0→ ไม่ตรง (และมี warning)
Warning ที่เกิดขึ้น
Warning | 1292 | Truncated incorrect DOUBLE value: 'David_Miller_789'
Warning | 1292 | Truncated incorrect DOUBLE value: '563_John'
Warning | 1292 | Truncated incorrect DOUBLE value: '1001_Carol_Taylor'
Warning | 1292 | Truncated incorrect DOUBLE value: '456_AdamSmith'
แนวทางปฏิบัติที่ดีกว่า
- หลีกเลี่ยง Implicit Cast — ใช้ CAST ชัดเจน:
WHERE CAST(StudentId AS UNSIGNED) = 456 - ออกแบบ Schema ให้ถูกต้อง — แยกเก็บ ID (INT) และ Name (VARCHAR) คอลัมน์ต่างกัน
- ใช้ LIKE สำหรับ prefix:
WHERE StudentId LIKE '456_%'
สรุป: MySQL ทำ implicit cast แบบ "อ่านตัวเลขนำหน้า" ซึ่งอาจให้ผลลัพธ์ไม่คาดคิดและมี warning ควรระบุ type conversion ชัดเจนหรือออกแบบ schema ให้เหมาะสม