Сравните диапазон IP-адресов с начальным и конечным IP-адресом в MySQL - PullRequest
1 голос
/ 15 июня 2010

У меня есть таблица MySQL, где я храню диапазоны IP-адресов. Это настроено таким образом, что у меня есть начальный адрес, сохраненный как long, и конечный адрес (и идентификатор и некоторые другие данные). Теперь у меня есть пользователи, добавляющие диапазоны путем ввода начального и конечного IP-адреса, и я хотел бы проверить, нет ли нового диапазона (частично) в базе данных.

Я знаю, что могу сделать запрос между запросами, но, похоже, он не работает с 2 разными столбцами, и я также не могу понять, как передать диапазон для его сравнения. Делать это в цикле в PHP возможно, но с диапазоном, например 132.0.0.0-199.0.0.0 достаточно большое количество запросов ..

Ответы [ 4 ]

2 голосов
/ 15 июня 2010

Когда вы говорите, что адреса хранятся как 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))

, т. е. новый диапазон не перекрываетстарый диапазон при условии, что он либо начинается после него, либо заканчивается до него.

1 голос
/ 15 июня 2010

Как насчет сохранения диапазонов адресов IP в десятичном виде, чтобы вы могли выполнять простые проверки с помощью BETWEEN.

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

1 голос
/ 15 июня 2010

И start_address, и end_address длинные? Тогда почему бы просто не преобразовать искомый IP в long и сделать 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)

Первая группа находит диапазоны, которые включают начальный адрес. Второй находит диапазоны, которые охватывают конечный адрес. Это означает, что все еще существует вероятность того, что введенный диапазон является расширенным набором диапазона в БД. Вот что проверяет третий.

Это должно вернуть вам все диапазоны, которые пересекают ваш введенный диапазон ...

0 голосов
/ 15 июня 2010

Как насчет чего-то вроде:

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

Это должно дать вам все существующие адреса, которые будут перекрывать новый адрес.

...