Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples in this guide work on VillageSQL. Install Now →
Most MySQL schemas store IP addresses as VARCHAR(45). It works, but it wastes space, does nothing to validate the format, and sorts lexicographically instead of numerically — so 192.168.1.10 sorts before 192.168.1.9. VillageSQL’s INET type fixes all of this and handles IPv4 and IPv6 in the same column.

The MySQL Default: VARCHAR

The straightforward approach:
VARCHAR(45) stores whatever string you give it. There’s no validation — 'not-an-ip' inserts without error. Sorting doesn’t follow numerical order, and comparing against a subnet requires string manipulation or conversion functions.

The Standard Workaround: INT UNSIGNED + INET_ATON

For IPv4, MySQL’s INET_ATON() converts a dotted-decimal string to a 4-byte integer. This is compact and sorts correctly:
This works well for IPv4-only schemas. The problem is IPv6: INT UNSIGNED can’t hold a 128-bit address. You’d need VARBINARY(16) and INET6_ATON() / INET6_NTOA() for IPv6, meaning a schema change when IPv6 support is needed.

With VillageSQL: The INET Type

VillageSQL’s vsql_network_address extension adds a native INET type that stores both IPv4 and IPv6 addresses in a compact binary format — 7 bytes for IPv4, 19 bytes for IPv6 — with validation on insert.
Invalid addresses are rejected at insert time — no application-layer validation needed.

Working with stored addresses

Indexing

Choosing a Storage Approach

For new schemas that need both IPv4 and IPv6 with built-in validation, INET is the cleanest option. For IPv4-only schemas with no VillageSQL dependency, INT UNSIGNED with INET_ATON / INET_NTOA is the established approach. For subnet queries against stored addresses, see Querying by Subnet in MySQL.

Frequently Asked Questions

Can INET store addresses with a netmask, like 192.168.1.5/24?

Yes. INET allows host bits — 192.168.1.5/24 is valid. If you want to enforce that host bits are zero (pure network addresses), use the CIDR type instead.

Does INET validate the address on insert?

Yes. inet_from_string('not-an-ip') returns NULL rather than storing garbage. If you pass NULL to an INET column with a NOT NULL constraint, the insert fails.

How does ORDER BY ip_address sort mixed IPv4/IPv6?

IPv4 addresses sort before IPv6 addresses. Within each family, addresses sort numerically. This matches PostgreSQL’s INET sort order.

Is INET the same as PostgreSQL’s inet type?

Functionally yes — same types (INET, CIDR, MACADDR, MACADDR8), same function naming conventions, same validation rules. The main difference is that VillageSQL provides functions rather than operators for comparisons and subnet checks.

Troubleshooting

See also