PostgreSQL IP地址:通过inet数据搜索正确的结果?



我在PostgreSQL上询问给定的IP地址(inet类型)是否在数据库中搜索正确的结果时遇到问题。我将逐步提供我正在做的事情。

CREATE TABLE public.test (
ip inet,
a character varying
);
INSERT INTO public.test (ip, a) VALUES
('1111:0000:0101:000A:0002:0003:0004:0005', 'admin1'),
('1111:0001:0101:000A:0002:0003:0004:0005', 'admin2'),
('1111:0011:0101:000A:0002:0003:0004:0005', 'admin3'),
('1111:0111:0101:000A:0002:0003:0004:0005', 'admin4'),
('1111:1111:0101:000A:0002:0003:0004:0005', 'admin5');

然后我想按'1111:0'搜索ip,这应该找到结果

1111:0000:0101:000A:0002:0003:0004:0005
1111:0001:0101:000A:0002:0003:0004:0005
1111:0011:0101:000A:0002:0003:0004:0005
1111:0111:0101:000A:0002:0003:0004:0005

如果要搜索inet地址的某些文本表示形式(使用f.ex。LIKE),你会很难过;因为inet输出是规范的。F.ex.:

input                                   | output 
1111:0000:0000:0000:0000:0000:0000:0005 | 1111::5/128
1111:0001:0101:000A:0002:0003:0004:0005 | 1111:1:101:a:2:3:4:5/128

因此,前导零消失了,只有零的最大块被替换为::(这在IPv6中完全有效)。

但是,如果要查找具有 20个前导位inet地址,例如1111:0,您可以使用子网。

对于1111:0,您实际上是在寻找1111::/20的子(网络/)主机(包含运算符:>>):

select addr,
inet '1111::/20' >> addr  "is within '1111::/20'"
from   (values (inet '1111:0000:0000:0000:0000:0000:0000:0005'),
(inet '1111:0001:0101:000A:0002:0003:0004:0005'),
(inet '1111:0011:0101:000A:0002:0003:0004:0005'),
(inet '1111:0111:0101:000A:0002:0003:0004:0005'),
(inet '1111:1111:0101:000A:0002:0003:0004:0005'),
(inet '1111:F111:0101:0000:0000:0000:0000:0005')) v(addr)

将产生:

addr                        | is within '1111::/20'
1111::5/128                 | t
1111:1:101:a:2:3:4:5/128    | t
1111:11:101:a:2:3:4:5/128   | t
1111:111:101:a:2:3:4:5/128  | t
1111:1111:101:a:2:3:4:5/128 | f
1111:f111:101::5/128        | f

http://rextester.com/ZFFFK28291

select * from test where 
cast((ip)as varchar) like '%a000::%'
or cast((ip)as varchar) like '%a000:_:%'
or cast((ip)as varchar) like '%a000:__:%'
or cast((ip)as varchar) like '%a000:___:%
or cast((ip)as varchar) like '%a000:_____'
or cast((ip)as varchar) like '%a000:______'
or cast((ip)as varchar) like '%a000:_______'

最新更新