VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
INET6_ATON() and INET6_NTOA() for this, and they work — but mixing IPv4 and IPv6 in one column requires extra care. VillageSQL’s INET type stores both families in one column with a consistent API.
MySQL’s IPv6 Approach: VARBINARY(16)
MySQL 5.6 addedINET6_ATON() and INET6_NTOA() for binary IPv6 storage. INET6_ATON() handles both IPv4 and IPv6:
INET6_NTOA() returns IPv4 in dotted-decimal and IPv6 in compressed notation. The column VARBINARY(16) holds both. This is the standard approach and it works.
The friction is in operations that need to know which family a row contains:
VARBINARY column.
With VillageSQL: Unified INET Type
VillageSQL’svsql_network_address extension provides an INET type that stores both IPv4 and IPv6 natively. The same functions work for both families — no length checks or separate code paths needed.
Working with IPv6 specifically
IPv6 addresses are stored and retrieved in expanded notation:Filtering by address family
MySQL vs VillageSQL for IPv6
| Approach | Stores IPv6 | Family detection | Prefix support | Validates on insert |
|---|---|---|---|---|
VARCHAR(45) | Yes | Manual string check | No | No |
VARBINARY(16) + INET6_ATON | Yes | LENGTH() = 16 | No | No (returns NULL on bad input) |
INET (VillageSQL) | Yes | inet_family() = 6 | Yes | Yes |
Frequently Asked Questions
Does the INET type store IPv4 in IPv4-mapped IPv6 format (::ffff:x.x.x.x)?
No — IPv4 addresses are stored as native IPv4, not as IPv4-mapped IPv6.inet_family() returns 4 for IPv4 addresses regardless of how they were written.
Does INET handle IPv6 compressed notation like ::1?
Yes.inet_from_string('::1') and inet_from_string('fe80::1') both parse correctly. Compressed notation is accepted on input; output is always the expanded form.
Can I index an INET column for fast lookups?
Yes —CREATE INDEX idx_ip ON access_log(ip_address) works. Equality lookups and range scans (for subnet queries) use the index. See Querying by Subnet in MySQL for the pattern.
Is VARBINARY(16) + INET6_ATON wrong?
No — it’s the correct MySQL-only approach. It’s more compact than INET (4 or 16 bytes vs 7 or 19), but you lose built-in family detection, prefix handling, and validation. For schemas that need to work across both IPv4 and IPv6 with prefix-aware operations,INET is more ergonomic.
Troubleshooting
| Problem | Solution |
|---|---|
FUNCTION inet_from_string does not exist | Run INSTALL EXTENSION vsql_network_address |
| IPv6 addresses display in expanded form | Expected — 2001:db8::1 stores as 2001:0db8:0000:0000:0000:0000:0000:0001 |
inet_from_string() returns NULL for a valid IPv6 | Check for typos; try the address in expanded form to isolate the issue |
INET6_ATON returns different values than inet_from_string | The underlying binary differs in size (4 vs 7 bytes for IPv4); they’re not interchangeable |

