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

问题描述:

当询问给定的IP地址(inet类型)是否在数据库中搜索正确的结果时,我在PostgreSQL上遇到问题。我将一步一步提供我正在做的事情。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中)。

但是,如果你想找到inet addresses,其中有20 领先位1111:0,你可以使用subnets

1111:0,你真正需要的孩子(网络/)的1111::/20(与contains operator: >>)主机:

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

+0

就像你说的那样,我们可以搜索正确的ip字符串(1111:0)。如果ip在中间或末尾匹配,这种方式不能解决这个问题。 – ggg

+0

@ggg是的,你不能在'inet'内搜索,因为它的输出是标准化的。您可以(理论上)在经过标准化的表格内进行搜索,但这不会相同(请参阅链接的rextester示例)。 – pozs

+0

我找到一种方法,我们不仅可以搜索作为字符串头部的ip,还可以搜索字符串'1111:0'位于中间还是结尾。 – ggg

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:_______' 
+0

但是,这如何帮助在f.ex中搜索'1111:0'。 '1111:1:101:A:2:3:4:5'?这只会在您只搜索一个区块时起作用。如果那样的话,你也可以使用一个'LIKE'。 – pozs