PostgreSQL为IPv4、IPv6以及以太网MAC地址都提供了特有的类型,使用这些类型存储IP地址、MAC地址相对于用字符串存储这些类型来说,不容易产生歧义,同时提供了相应的函数让IP地址的运算更方便,本节将详细讲解这些类型的使用方法。
PostgreSQL提供了专门的数据类型来存储IPv4、IPv6和MAC地址。这比使用字符串效果更好一些,因为使用这些类型有助于更好地做检测。涉及的类型见表5-25。
表5-25 网络地址类型列表
inet和cidr类型都可以用于存储一个IPv4或IPv6的地址,示例如下:
osdba=# select '192.168.1.100'::inet; inet --------------- 192.168.1.100 (1 row) osdba=# select '192.168.1.100'::cidr; cidr ------------------ 192.168.1.100/32 (1 row)
这两种类型输入IPv4地址的格式相同,具体如下:
x.x.x.x/masklen
其掩码可以省略,格式如下:
x.x.x.x
注意,掩码的长度都是用一个数字表示的,不能使用如下格式:
osdba=# select '198.168.1.100/255.255.255.0'::cidr; ERROR: invalid input syntax for type cidr: "198.168.1.100/255.255.255.0" LINE 1: select '198.168.1.100/255.255.255.0'::cidr; ^ osdba=# select '198.168.1.100 255.255.255.0'::inet; ERROR: invalid input syntax for type inet: "198.168.1.100 255.255.255.0" LINE 1: select '198.168.1.100 255.255.255.0'::inet; ^
IPv6地址的输入格式如下:
ipv6_addr/masklen
其中ipv6_addr可以使用标准的IPv6地址表示方式,即分为8组,每组为4个十六进制数的形式,具体格式如下:
DA70:0000:0000:0000:ABCD:0000:00F7:0003
如果觉得上面的表示方法太长,还可以使用零压缩法缩短输入。如果几个连续段位的值都是“0”,那么这些“0”就可以简单地以“::”来表示,上面的输入就可以压缩表示如下:
DA70::ABCD:0000:00F7:0003
需要注意的是,只能简化连续为“0”的组,每个组中间和后面的“0”都要保留,比如“DA70”最后的这个“0”不能简化,并且这种简化方式只能用一次,上例中“ABCD”后面的“0000”就不能再进行简化了。这个限制是为了能准确还原被压缩的“0”,不然就无法确定每个“::”究竟代表多少个“0”。不过,各组前导的“0”是可以省略的,如“DA70::ABCD:0000:00F7:0003”与“DA70::ABCD:0000:F7:3”是相同的。
以下几个IPv6地址都是等价的:
DA70:0000:0000:0000:ABCD:0000:00F7:0003 DA70:0000::ABCD:0000:00F7:0003 DA70::ABCD:0000:00F7:0003 DA70:0000:0000:0000:ABCD::00F7:0003 DA70::ABCD:0:F7:3
一个IPv6地址可以将一个IPv4地址内嵌进去,这样就把IPv6的地址写成了IPv6地址和IPv4地址混合的形式。IPv6内嵌IPv4的方式有两种:
·IPv4映像地址。
·IPv4兼容地址。
IPv4映像地址格式如下:
::ffff:192.168.1.100
这个地址仍然是一个IPv6地址,是“::ffff:c0a8:164”的另一种写法。
IPv4兼容地址的写法如下:
::192.168.1.100
这个地址仍然是一个IPv6地址,它是“::c0a8:164”的另一种写法。
对于inet来说,如果子网掩码是32并且地址是IPv4,那么它不表示任何子网,所表示的只是一台主机的地址,示例如下:
osdba=# select '192.168.1.100/32'::inet; inet --------------- 192.168.1.100 (1 row)
同样,IPv6地址长度是128位,因此在inet中128位的掩码也表明是一个主机地址,而不是一个子网地址:
osdba=# select '::10.2.3.4/128'::inet; inet ------------ ::10.2.3.4 (1 row)
而cidr总是显示出掩码,示例如下:
osdba=# select '198.168.1.100'::cidr; cidr ------------------ 198.168.1.100/32 (1 row) osdba=# select '198.168.1.100/32'::cidr; cidr ------------------ 198.168.1.100/32 (1 row)
cidr总是对地址与掩码之间的关系进行检查,如果不正确会报错,示例如下:
osdba=# select '192.168.1.100/16'::inet; inet ------------------ 192.168.1.100/16 (1 row) osdba=# select '192.168.1.100/16'::cidr; ERROR: invalid cidr value: "192.168.1.100/16" LINE 1: select '192.168.1.100/16'::cidr; ^ DETAIL: Value has bits set to right of mask.
macaddr类型用于存储以太网的MAC地址,可以接受多种自定义格式,示例如下:
'00:e0:4c:75:7d:5a' '00-e0-4c-75-7d-5a' '00e04c-757d5a' '00e04c:757d5a' '00e0.4c75.7d5a' '00e04c757d5a'
上面声明的是同一个MAC地址。对于数据位中的“a”到“f”,大小写都可以。输出总是上面的第一种形式,示例如下:
osdba=# select '00e04c757d5a'::macaddr; macaddr ------------------- 00:e0:4c:75:7d:5a (1 row) osdba=# select '00e04c:757d5a'::macaddr; macaddr ------------------- 00:e0:4c:75:7d:5a (1 row) osdba=# select '00-e0-4c-75-7d-5a'::macaddr; macaddr ------------------- 00:e0:4c:75:7d:5a (1 row)
可用于cidr类型和inet类型的操作符及其示例见表5-26。
表5-26 cidr和inet类型的操作符
macaddr类型支持一些简单的比较运算符和位运算符,具体见表5-27。
表5-27 macaddr类型支持的操作符
可以用于cidr类型和inet类型的函数及其示例见表5-28。
表5-28 网络地址类型函数
可用于macaddr类型的函数只有一个trunc(macaddr),此函数把MAC地址的后3个字节置为0,示例如下:
osdba=# select trunc(macaddr '00e04c757d5a'); trunc ------------------- 00:e0:4c:00:00:00 (1 row)