2010-06-15 167 views
1

我有一個MySQL表,我存儲IP範圍。它的設置方式是我將起始地址存儲爲一個長整數,並且結束地址(以及一個id和一些其他數據)。 現在我有用戶通過輸入開始和結束IP地址來添加範圍,並且我想檢查新範圍是否已經(部分)在數據庫中。比較ip地址與MySQL中的開始和結束ip地址的範圍

我知道我可以做一個查詢,但似乎並不適用於2個不同的列,我也無法弄清楚如何通過一個範圍來比較它。 在PHP中進行循環操作是一種可能性,但可以使用一系列132.0.0.0-199.0.0.0是相當大的量查詢..

回答

2

當你說你有存儲爲long地址,我假設你的意思是你已經得到了他們存儲,使得(比如說)10.1.2.3將被存儲爲0x0a010203。在這種情況下,要找到一個地址是否已經存在,你可以這樣做:

SELECT ... 
FROM ipranges 
WHERE (<NEWADDR> >= startaddr) 
    AND (<NEWADDR> <= endaddr) 

,然後如果你得到任何排之後,該地址已經在表中。 (使用新的地址替換<NEWADDR>,當然!)

至於檢查重疊行,這只是稍微複雜一點:

SELECT ... 
FROM ipranges 
WHERE NOT ((<NEWENDADDR> < startaddr) OR (<NEWSTARTADDR> > endaddr)) 

即新的範圍不會重疊,條件是它老範在它之後開始,或者在它之前結束。

+0

重疊邏輯看起來有點超過我的頭,現在對我有意義,謝謝尋求幫助。在PHP中已經想到了一個不錯的循環,但效率並不是很低,但這仍然快得多 – Maarten 2010-06-15 14:11:38

0

約像什麼:

SELECT * FROM addresses WHERE 
    (start < $new_start AND end > $new_start) OR 
    (start > $new_end AND end < $new_end); 

這應該給你的所有,這將重疊的新地址的現有地址。

+0

如果有什麼新的範圍完全包圍老範?例如,如果舊範圍是(start = 99,end = 100),新範圍是($ new_start = 1,$ new_end = 200)?我不認爲你的查詢會返回這個結果:-( – psmears 2010-06-15 13:35:20

+0

那麼這是一個簡單的附加子句: 'OR(start> = $ new_start AND end <= $ new_end)' – 2010-06-15 16:24:38

1

start_address和end_address都是long?那麼爲什麼不把你想要的IP轉換成很長時間呢?WHERE start_address <= $myip AND end_address >= $myip

對於一個範圍,只是做了三次where子句

WHERE (start_address <= $startAddress AND end_address >= $startAddress) 
    OR (start_address <= $endAddress AND end_address >= $endAddress) 
    OR (start_address >= $startAddress AND end_address <= $endAddress) 

中的第一組認定,包括起始地址範圍。第二個找到包含結束地址的範圍。這意味着輸入的範圍仍然有可能是db中範圍的超集。這是第三次檢查的結果。

應該返回你所有的相交輸入範圍範圍...

+0

你實際上並不需要三種情況 - 更容易檢查範圍*不重疊的情況(即,新的範圍要麼低於現有的範圍,要麼完全高於此範圍),然後使用'NOT'來反轉結果:-) – psmears 2010-06-15 13:25:37

1

如何將IP地址範圍存儲爲十進制數,您可以使用BETWEEN進行簡單檢查。

4294967295 - 4294967040 - > FFFFFF00 - FFFFFFFF - > 255.255.255.0 - 255.255.255.255