4

我想将 inet 格式的 IPv4 地址转换为整数组件。

例如,将 '101.255.30.40' 变成 oct1=101, oct2=255, oct3=30, oct4=40。

如果我将 inet 转换为 varchar,则应该使用正则表达式来执行此操作,但这似乎不优雅。是否有用于返回 inet 的第 n 个八位字节的 1 行函数?

select inet_to_octet('101.255.30.40', 4) as temp;  -- returns temp=40?
4

3 回答 3

3

除非您想尝试将函数贡献给 inet 数据类型,否则您需要依赖基于字符串的版本。也许将这样的东西(但有一些错误检查)放入 SQL 函数中以便于访问?:

CREATE OR REPLACE FUNCTION extract_octet(inet, integer) RETURNS integer AS $$
    SELECT ((regexp_split_to_array(host($1), E'\\.'))[$2])::int;
$$ LANGUAGE SQL;



select extract_octet(inet '192.26.22.2', 2)

Output: 26
于 2013-04-01T21:53:04.140 回答
3

终于从同事那里得到了很好的答案...

对于某些风格的 sql,使用“split_part”和 host(inet) 来获取文本字段。

select split_part(host('101.255.30.40'::inet), '.', 1);
select split_part(host('101.255.30.40'::inet), '.', 2);
select split_part(host('101.255.30.40'::inet), '.', 3);
select split_part(host('101.255.30.40'::inet), '.', 4);

结果是

101
255
30
40

如果您想更复杂地处理 IPv6,请使用掩码来加速操作以及使用 case 语句来获取 IP 版本:

select
   (case
      when family('101.255.30.40'::inet) = 4 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 32))), '.', 4)::varchar
      when family('101.255.30.40'::inet) = 6 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 64))), ':', 4)::varchar
      else null end)::varchar as octet4;

select
   (case
      when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 4 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 32))), '.', 4)::varchar
      when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 6 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 64))), ':', 4)::varchar
      else null end)::varchar as octet4;

结果是

40
80b0

如果您想将 IPv6 转换为数字,则可以在 case 语句中添加十六进制到整数的转换。

于 2014-01-24T19:09:36.517 回答
2

下面是几个用于 IPv4 地址的单独八位字节的单行代码:

SELECT substring(host('1.2.3.4'::inet) FROM '^([0-9]+)\.[0-9]+\.[0-9]+\.[0-9]+$');

将返回1

SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.([0-9]+)\.[0-9]+\.[0-9]+$');

将返回2

SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.[0-9]+\.([0-9]+)\.[0-9]+$');

将返回3

SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+)$');

将返回4

于 2013-04-01T21:49:29.597 回答