Mysql
 sql >> база данни >  >> RDS >> Mysql

Търсене на частични IP адреси, съхранени като цели числа

Всъщност колоната с цяло число без знак вече е най-ефективният начин за търсене на съвпадения на частични IP адреси! Моля, не си губете енергията или времето на процесора, за да преобразувате обратно в нотация с точки или да търсите LIKE в някаква колона с низове.

Съществуват няколко начина за записване на частичен IP адрес, но в крайна сметка всички те се свеждат до базов IP с мрежова маска. Освен това, ако приемем, че под частични имате предвид всички IP адреси с общ префикс, тогава това също е еквивалентно на определяне на диапазон от IP адреси.

Така или иначе, частичната спецификация на IP адреса в крайна сметка се описва като две 32 бита, цели числа без знак, кодирани в същия формат като колоната на вашата база данни. Или имате начален и краен ip, или имате базов IP и маска. Тези цели числа могат да се използват директно във вашата SQL заявка за ефективно получаване на съвпадения. Още по-добре, ако използвате подхода за IP диапазон, тогава двигателят ще може да се възползва от подреден индекс във вашата ip колона. Не можете да очаквате по-добро.

И така, как да изградим IP обхвата? Това ще зависи от това как са били посочени вашите частични адреси на първо място, но ако приемем, че знаете маската на мрежата, тогава началният адрес е равен на (базов IP и мрежова маска), а крайният адрес е ((базов IP &мрежова маска) | (~мрежова маска)), където &, | и ~ означава съответно побитово-и, побитово-или и побитово-не.

Актуализиране

Ето примерен код за прилагане на описаната от мен стратегия.

Измина много време, откакто за последно написах PHP код и следното никога не е било изпълнено, така че моля, извинете всяка грешка, която може да съм въвел. Също така избрах умишлено да „разширя“ всеки сценарий на нотация, за да ги улесня разбирането, вместо да ги стискам в един, много сложен регулярен израз.

if (preg_match(' /^ (\d{1,3}) [.] (\d{1,3}) [.] (\d{1,3}) [.] (\d{1,3}) [/] (\d{1,2}) $/x', $input, $r)) {
    // Four-dotted IP with number of significant bits: 123.45.67.89/24

    $a = intval($r[1]);
    $b = intval($r[2]);
    $c = intval($r[3]);
    $d = intval($r[4]);
    $mask = intval($r[5]);

} elseif (preg_match(' /^ (\d{1,3}) (?: [.] [*0] [.] [*0] [.] [*0] )? $/x', $input, $r)) {
    // Four-dotted IP with three-last numbers missing, or equals to 0 or '*':
    // 123.45, 123.45.0.0, 123.45.*.*  (assume netmask of 8 bits)

    $a = intval($r[1]);
    $b = 0;
    $c = 0;
    $d = 0;
    $mask = 8;

} elseif (preg_match(' /^ (\d{1,3}) [.] (\d{1,3}) (?: [.] [*0] [.] [*0] )? $/x', $input, $r)) {
    // Four-dotted IP with two-last numbers missing, or equals to 0 or '*':
    // 123.45, 123.45.0.0, 123.45.*.*  (assume netmask of 16 bits)

    $a = intval($r[1]);
    $b = intval($r[2]);
    $c = 0;
    $d = 0;
    $mask = 16;

} elseif (preg_match(' /^ (\d{1,3}) [.] (\d{1,3}) [.] (\d{1,3}) (?: [.] [*0] )? $/x', $input, $r)) {
    // Four-dotted IP with last number missing, or equals to 0 or *:
    // 123.45.67, 123.45.67.0, 123.45.67.*  (assume netmask of 24 bits)

    $a = intval($r[1]);
    $b = intval($r[2]);
    $c = intval($r[3]);
    $d = 0;
    $mask = 24;

} elseif (preg_match(' /^ (\d{1,3}) [.] (\d{1,3}) [.] (\d{1,3}) [.] (\d{1,3}) $/x', $input, $r)) {
    // Four-dotted IP: 123.45.67.89 (assume netmask of 32 bits)

    $a = intval($r[1]);
    $b = intval($r[2]);
    $c = intval($r[3]);
    $d = intval($r[4]);
    $mask = 32;

} else {
    throw new Exception('...');
}

if ($a < 0 || $a > 255) {  throw new Exception('...') };
if ($b < 0 || $b > 255) {  throw new Exception('...') };
if ($c < 0 || $c > 255) {  throw new Exception('...') };
if ($d < 0 || $d > 255) {  throw new Exception('...') };
if ($mask < 1 || $mask > 32) {  throw new Exception('...') };

$baseip = ($a << 24) + ($b << 16) + ($c << 8) + ($d);
$netmask = (1 << (32 - $mask)) - 1;

$startip = $baseip & netmask;
$endip = ($baseip & netmask) | (~netmask);

// ...

doSql( "SELECT ... FROM ... WHERE ipaddress >= ? && ipaddress <= ?", $startip, $endip);

// or

doSql( "SELECT ... FROM ... WHERE ((ipaddress & ?) = ?)", $netmask, $startip);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Обединете таблици в две бази данни с помощта на SQLAlchemy

  2. Съкращаване с условие

  3. Сценарии за архивиране и възстановяване на MySQL в облак с помощта на Microsoft Azure

  4. Минимални и максимални стойности на Mysql и съответната дата за всеки месец

  5. MySQL:Изберете N реда, но само с уникални стойности в една колона