从 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的主要内容,如果未能解决你的问题,请参考以下文章

sql 从IP子网掩码中获取CIDR('/')。

如何使用python获取ip和子网掩码地址[关闭]

以编程方式获取网关和子网掩码详细信息

python设置本机IP地址子网掩码DNS,获取本机IP地址子网掩码DNSMAC

Python通过snmp获取交换机VLAN号VLAN默认网关VLAN子网掩码和ARP表中的IP地址与MAC对应记录数据

Python通过snmp获取交换机VLAN号VLAN默认网关VLAN子网掩码和ARP表中的IP地址与MAC对应记录数据