การแปลง IPv4 Address ระหว่างสตริงและตัวเลขด้วย INET_ATON / INET_NTOA
MySQL มีฟังก์ชัน built-in สำหรับแปลง IP address (IPv4) ระหว่างรูปแบบ dotted-quad string และ unsigned integer 32-bit
สร้างตารางและข้อมูล
mysql> create table DemoTable1404 (
-> IpAddress varchar(40)
-> );
Query OK, 0 rows affected (1.02 sec)
mysql> insert into DemoTable1404 values('192.168.120.0');
mysql> insert into DemoTable1404 values('192.168.120.20');
mysql> insert into DemoTable1404 values('224.0.0.0');
ข้อมูลต้นฉบับ
+----------------+ | IpAddress | +----------------+ | 192.168.120.0 | | 192.168.120.20 | | 224.0.0.0 | +----------------+
คำสั่งแปลงเป็น INTEGER (INET_ATON)
mysql> select inet_aton(IpAddress) from DemoTable1404;
ผลลัพธ์
+----------------------+ | inet_aton(IpAddress) | +----------------------+ | 3232266240 | | 3232266260 | | 3758096384 | +----------------------+
คำสั่งแปลงกลับเป็น STRING (INET_NTOA)
mysql> select inet_ntoa('3232266240');
ผลลัพธ์
+-------------------------+
| inet_ntoa('3232266240') |
+-------------------------+
| 192.168.120.0 |
+-------------------------+
หลักการคำนวณ
IPv4 = 4 octets (a.b.c.d) → Integer = a×256³ + b×256² + c×256¹ + d×256⁰
192.168.120.0 = 192×16777216 + 168×65536 + 120×256 + 0
= 3221225472 + 11010048 + 30720 + 0
= 3232266240
ข้อดีของการเก็บเป็น INTEGER
- ประหยัดพื้นที่: 4 bytes (INT UNSIGNED) vs 15 bytes (VARCHAR(15))
- เร็วกว่า: เปรียบเทียบตัวเลขได้โดยตรง ใช้ index ได้ดี
- Range query:
WHERE ip_int BETWEEN inet_aton('192.168.1.0') AND inet_aton('192.168.1.255') - Sort ให้ถูกต้องตามลำดับ IP (VARCHAR เรียงแบบ lexicographic ผิด: 192.168.1.10 < 192.168.1.2)
IPv6: INET6_ATON / INET6_NTOA (MySQL 5.6+)
SELECT INET6_ATON('2001:db8::1'); -- VARBINARY(16)
SELECT INET6_NTOA(INET6_ATON('::1')); -- ::1
เก็บเป็น VARBINARY(16) หรือ BINARY(16)
Schema แนะนำ
CREATE TABLE ip_logs (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
ip_int INT UNSIGNED NOT NULL, -- IPv4
-- ip_bin VARBINARY(16), -- IPv6
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_ip (ip_int)
);