ปัญหา
วันที่เก็บอยู่ใน VARCHAR ด้วยรูปแบบเฉพาะ (เช่น DD/MM/YYYY) ต้องการเปรียบเทียบกับวันที่ปัจจุบัน (CURDATE()) ซึ่งเป็น DATE Type
วิธีแก้: ใช้ STR_TO_DATE() แปลง String → DATE
STR_TO_DATE(str, format) แปลงสตริงเป็น DATE/DATETIME ตาม Format Specifier
Format Specifiers พื้นฐาน
| Specifier | ความหมาย | ตัวอย่าง |
|---|---|---|
| %d | วัน (00-31) | 27 |
| %m | เดือน (00-12) | 10 |
| %Y | ปี 4 หลัก | 2019 |
| %y | ปี 2 หลัก | 19 |
| %H | ชั่วโมง 24h (00-23) | 14 |
| %i | นาที (00-59) | 30 |
| %s | วินาที (00-59) | 45 |
ตัวอย่างการใช้งาน
1. สร้างตาราง (เก็บวันที่เป็น VARCHAR)
mysql> CREATE TABLE DemoTable (
-> JoiningDate VARCHAR(40)
-> );
Query OK, 0 rows affected (0.79 sec)
2. เพิ่มข้อมูล
mysql> INSERT INTO DemoTable VALUES('27/10/2017');
Query OK, 1 row affected (0.14 sec)
mysql> INSERT INTO DemoTable VALUES('27/10/2018');
Query OK, 1 row affected (0.78 sec)
mysql> INSERT INTO DemoTable VALUES('27/10/2019');
Query OK, 1 row affected (0.14 sec)
mysql> INSERT INTO DemoTable VALUES('27/10/2020');
Query OK, 1 row affected (0.11 sec)
3. ค้นหาแถวที่ตรงกับวันที่ปัจจุบัน (สมมติวันนี้ 27/10/2019)
mysql> SELECT * FROM DemoTable
-> WHERE STR_TO_DATE(JoiningDate, '%d/%m/%Y') = CURDATE();
ผลลัพธ์:
+-------------+ | JoiningDate | +-------------+ | 27/10/2019 | +-------------+ 1 row in set (0.00 sec)
ข้อควรระวังเรื่อง Performance
- STR_TO_DATE() ทำ Full Table Scan → ไม่ใช้ Index บน JoiningDate ได้
- แก้ไข: สร้าง Generated Column (MySQL 5.7+)
สร้าง Generated Column สำหรับ Index
ALTER TABLE DemoTable ADD COLUMN JoiningDateParsed DATE GENERATED ALWAYS AS (STR_TO_DATE(JoiningDate, '%d/%m/%Y')) STORED, ADD INDEX idx_joining_date (JoiningDateParsed);
แล้ว Query แบบนี้จะใช้ Index ได้
SELECT * FROM DemoTable WHERE JoiningDateParsed = CURDATE();
Best Practice
- เก็บวันที่ใน DATE/DATETIME Type ตั้งแต่แรก (หลีกเลี่ยง VARCHAR)
- ใช้ Application Layer แปลง Format ก่อน Insert
- หากต้องเก็บ String ให้เพิ่ม Generated Column สำหรับ Query/Index
- ใช้
DATE_FORMAT()สำหรับแสดงผล (DATE → String)
ฟังก์ชันเกี่ยวข้อง
DATE_FORMAT(date, format)- DATE → String (แสดงผล)STR_TO_DATE(str, format)- String → DATE (Parse Input)CURDATE()- วันที่ปัจจุบัน (DATE)NOW()- วันที่เวลาปัจจุบัน (DATETIME)