> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL 的 vsql_network_address 扩展

> vsql_network_address 扩展为 MySQL 添加 INET、CIDR、MACADDR 和 MACADDR8 列类型，并提供包含、子网掩码和比较函数。

保存在 `VARCHAR` 中的 IP 地址按字母顺序排序，接受拼写错误，也无法
回答某个地址是否落在某个网络之内。`vsql_network_address` 添加了四种
列类型，它们验证输入、正确排序，并附带配套的包含和子网掩码函数。
它遵循 PostgreSQL 的 `inet`、`cidr`、`macaddr` 和 `macaddr8` 类型。

| | |
| - | - |
| **维护者** | VillageSQL |
| **源代码和完整文档** | [villagesql/vsql-network-address](https://github.com/villagesql/vsql-network-address) |
| **许可证** | GPL-2.0 |

## 安装

如果您使用安装脚本、Docker 镜像或发行版压缩包安装了 VillageSQL，
`vsql_network_address.veb` 已经位于服务器的 `lib/veb/` 目录中。
用一条语句将它安装到服务器中：

```sql theme={null}
INSTALL EXTENSION vsql_network_address;
```

确认它已存在：

```sql theme={null}
SELECT EXTENSION_NAME
FROM INFORMATION_SCHEMA.EXTENSIONS
WHERE EXTENSION_NAME = 'vsql_network_address';
```

```
+----------------------+
| EXTENSION_NAME       |
+----------------------+
| vsql_network_address |
+----------------------+
```

要自行构建，请按照[存储库](https://github.com/villagesql/vsql-network-address)中的
构建说明进行操作。

## 新增内容

### 类型

| 类型 | 保存内容 | 字节数 |
| - | - | - |
| `INET` | 带可选子网掩码的主机地址，IPv4 或 IPv6 | 19 |
| `CIDR` | 网络地址 | 19 |
| `MACADDR` | 6 字节硬件地址 | 6 |
| `MACADDR8` | 8 字节硬件地址 | 8 |

```sql theme={null}
CREATE TABLE hosts (
    id    INT PRIMARY KEY,
    label VARCHAR(16),
    addr  INET,
    mac   MACADDR
);
```

### 函数

| 函数 | 返回 | 作用 |
| - | - | - |
| `inet_from_string(s)`、`inet_to_string(a)` | `INET`、文本 | 在文本和 `INET` 之间转换 |
| `cidr_from_string(s)`、`cidr_to_string(c)` | `CIDR`、文本 | `CIDR` 的同类转换 |
| `macaddr_from_string(s)`、`macaddr_to_string(m)` | `MACADDR`、文本 | `MACADDR` 的同类转换 |
| `macaddr8_from_string(s)`、`macaddr8_to_string(m)` | `MACADDR8`、文本 | `MACADDR8` 的同类转换 |
| `inet_compare(a, b)`、`cidr_compare(a, b)`、`macaddr_compare(a, b)`、`macaddr8_compare(a, b)` | 整数 | -1、0 或 1 |
| `inet_contains(a, b)` | 整数 | `a` 严格包含 `b` 时为 1 |
| `inet_contains_or_equals(a, b)` | 整数 | `a` 包含 `b` 或与之相等时为 1 |
| `inet_contained_by(a, b)` | 整数 | `a` 严格位于 `b` 之内时为 1 |
| `inet_contained_by_or_equals(a, b)` | 整数 | `a` 位于 `b` 之内或与之相等时为 1 |
| `inet_overlaps(a, b)` | 整数 | 任一方包含另一方，或两者相等时为 1 |
| `inet_family(a)` | 整数 | 4 或 6 |
| `inet_masklen(a)` | 整数 | 子网掩码长度 |
| `inet_set_masklen(a, n)`、`cidr_set_masklen(c, n)` | `INET`、`CIDR` | 同一地址，换用不同的子网掩码 |
| `inet_host(a)`、`inet_text(a)`、`inet_abbrev(a)`、`cidr_abbrev(c)` | 文本 | 不带掩码的地址、带掩码的地址，以及缩写形式 |
| `inet_netmask(a)`、`inet_hostmask(a)` | `INET` | 子网掩码及其补码 |
| `inet_broadcast(a)` | `INET` | 所属网络的广播地址 |
| `inet_network(a)` | `CIDR` | 该地址所属的网络 |
| `macaddr_trunc(m)` | `MACADDR` | 后三个字节清零，只保留制造商前缀 |

## 示例

```sql theme={null}
INSERT INTO hosts VALUES
    (1, 'gateway', '192.168.1.1/24',  '00:1b:63:84:45:e6'),
    (2, 'printer', '192.168.1.50/24', '3c:22:fb:aa:01:02'),
    (3, 'vpn',     '10.8.0.7/16',     '00:1b:63:84:45:e7');

SELECT label, addr, inet_masklen(addr) AS mask, inet_family(addr) AS family
FROM hosts ORDER BY addr;
```

```
+---------+-----------------+------+--------+
| label   | addr            | mask | family |
+---------+-----------------+------+--------+
| vpn     | 10.8.0.7/16     |   16 |      4 |
| gateway | 192.168.1.1/24  |   24 |      4 |
| printer | 192.168.1.50/24 |   24 |      4 |
+---------+-----------------+------+--------+
```

各行按地址顺序而不是字母顺序返回。文本顺序会把 `9.0.0.1` 排在 `10.8.0.7` 之后；地址顺序把它排在前面。

询问哪些主机位于某个网络上：

```sql theme={null}
SELECT label FROM hosts
WHERE inet_contained_by_or_equals(addr, inet_from_string('192.168.1.0/24')) = 1;
```

```
+---------+
| label   |
+---------+
| gateway |
| printer |
+---------+
```

推导网络及其广播地址：

```sql theme={null}
SELECT inet_network(inet_from_string('192.168.1.50/24')) AS network,
       inet_broadcast(inet_from_string('192.168.1.50/24')) AS broadcast;
```

```
+----------------+------------------+
| network        | broadcast        |
+----------------+------------------+
| 192.168.1.0/24 | 192.168.1.255/24 |
+----------------+------------------+
```

> [!NOTE]
>
> `inet_contained_by` 是严格的，因此带有与网络相同子网掩码的地址不被
> 该网络包含。`192.168.1.5/32` 在 `192.168.1.0/24` 之内返回 1，而
> `192.168.1.5/24` 在同一网络之内返回 0。当存储的行带有网络自身的掩码
> 时（如上面的示例），请使用 `inet_contained_by_or_equals`。

## 另请参阅

* [在 MySQL 中存储 IP 地址](https://villagesql.com/docs/en/guides/storing-ip-addresses.md) — 在 INET、VARCHAR 和整数之间选择
* [子网查询](https://villagesql.com/docs/en/guides/subnet-queries.md) — 包含、重叠，以及每一种的含义
* [存储 MAC 地址](https://villagesql.com/docs/en/guides/storing-mac-addresses.md) — MACADDR 与 MACADDR8 的对比
* [安装扩展](https://villagesql.com/docs/zh/extensions/install.md) — `INSTALL EXTENSION` 如何工作，以及服务器在哪里查找包
* [可用扩展](https://villagesql.com/docs/zh/extensions/catalog) — 完整目录
* [villagesql/vsql-network-address](https://github.com/villagesql/vsql-network-address) — 源代码、构建说明和已知限制


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.