2010-06-15 173 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