2013-04-01 51 views
3

我想將一個inet格式的IPv4地址轉換爲整數部分。如何從postgres sql中提取inet值的八位組?

例如,轉向 '101.255.30.40' 進OCT1 = 101,辛= 255,OCT3 = 30,和Oct4 = 40。

有正則表達式應該這樣做,如果我投了INET爲VARCHAR,但似乎不雅。是否有1行函數用於返回inet的第n個八位字節?

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

有這個沒有標準功能,並記住,INET和CIDR領域也可以包含IPv6地址和前綴。 –

+0

對於我的具體應用,所有我的地址是IPv4的 –

+0

看起來我需要INET_ATON和INET_NTOA的Postgres的版本,所以我可以按照這樣的:http://www.hiregion.com/2010/07/converting-ip-address -to-integer-and.html –

回答

2

我終於從同事的出色答卷......

對於一些口味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語句中將十六進制轉換爲int轉換。

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

+0

工作原理 - 謝謝! –

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