2017-03-16 75 views
1

當詢問給定的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 

回答

2

如果你要搜索的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

0
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