从 postgres 中的子网/掩码获取 MAX 和 MIN ip
Posted
技术标签:
【中文标题】从 postgres 中的子网/掩码获取 MAX 和 MIN ip【英文标题】:Get MAX and MIN ip from subnet/mask in postgres 【发布时间】:2016-08-19 17:58:43 【问题描述】:我有以下问题:
现在我有一个包含子网/掩码信息的表(例如 192.168.1.0 / 255.255.255.0 )......但我需要从这个子网获取 MAX 和 MIN IP:
192.168.1.0 / 192.168.1.255
我找到了这个答案:
how to query for min or max inet/cidr with postgres
但似乎:
network_smaller(inet, inet) 和 network_larger(inet, inet)
不存在。甚至在谷歌上搜索我找不到这些功能的任何答案。
谢谢!
编辑:
版本信息:
x86_64-redhat-linux-gnu 上的 PostgreSQL 9.2.15,由 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4) 编译,64 位
【问题讨论】:
【参考方案1】:无论如何,我认为这个问题与您的需求无关。此处定义的 min 和 max 类似于 SQL min()
和 max()
函数,用于查找表中的最小/最大,而不是子网中的最小/最大。
我通常不喜欢依赖未记录的功能。它们可能是安全的,但可能不是我通常喜欢的词。
这里有一个记录网络功能的页面: https://www.postgresql.org/docs/current/static/functions-net.html
你需要的两个是:
最小值为network(inet)
最大值为broadcast(inet)
这是因为网络名称始终是该范围内的“第一个”ip,而广播地址始终是该范围内的“最后一个”ip。
【讨论】:
【参考方案2】:不要谷歌,试试看:
select network_smaller('192.168.0.9'::inet, '192.168.0.11'::inet);
network_smaller
-----------------
192.168.0.9
(1 row)
Postgres 有超过 2,600 个内部函数。它们中的大多数对于创建各种类型的运算符类很有用。并非所有这些都在文档中进行了描述,但它们都是普遍可用的。
您可以使用 pg_catalog 中的 pgAdmin III 找到它们。您只需要设置选项:文件 -> 选项 -> UI Miscellaneous -> Show System Objects in treeview。
Postgres 9.5 中引入了聚合函数 min(inet)
和 max(inet)
:
with test(ip) as (
values
('192.168.0.123'::inet),
('192.168.0.12'),
('192.168.0.1'),
('192.168.0.125')
)
select max(ip), min(ip)
from test;
max | min
---------------+-------------
192.168.0.125 | 192.168.0.1
(1 row)
查看聚合min(inet)
是如何定义的(可以在pg_catalog
中找到):
CREATE AGGREGATE min(inet) (
SFUNC=network_smaller,
STYPE=inet,
SORTOP="<"
);
问题How to query for min or max inet/cidr with postgres 涉及Postgres 9.4。在我的回答中,我建议使用函数network_smaller(inet, inet)
和network_larger(inet, inet)
。我确信它们是为创建聚合函数min(inet)
和max(inet)
而添加的,但由于某些原因(可能是疏忽),聚合只出现在 Postgres 9.5 中。
在 Postgres 9.2 中,您可以创建自己的函数作为替代,例如
create or replace function inet_larger(inet, inet)
returns inet language sql as $$
select case when network_gt($1, $2) then $1 else $2 end
$$;
create or replace function inet_smaller(inet, inet)
returns inet language sql as $$
select case when network_lt($1, $2) then $1 else $2 end
$$;
【讨论】:
好吧。我显然已经尝试过了.. 错误:函数 network_smaller(inet, inet) 不存在 提示:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。 只是一个问题。依赖这种未记录的功能有多安全? @PhilipCouling - 我们可以依赖内部函数吗?我认为是的,就所有运算符、索引、排序和大多数聚合都基于它们而言。以上是关于从 postgres 中的子网/掩码获取 MAX 和 MIN ip的主要内容,如果未能解决你的问题,请参考以下文章
python设置本机IP地址子网掩码DNS,获取本机IP地址子网掩码DNSMAC