Яндекс.Практикум

Работа с IP-адресами в SQL

Работа с IP-адресами в SQL

Есть много инструментов, которые позволяют работать с IP адресами, масками и сетям. Так вы можете использовать калькулятор на нашем сайте, а также специализированные библиотеки на Python или JavaScript. А еще у вас есть возможность применять функции и операции прямо базах данных с помощью SQL запросов.

Не все СУБД поддерживают эти операции, но если ваши данные хранятся в PostgreSQL, то вы можете воспользоваться его встроенными средствами для работы с IP-адресами и сетями.

Если вы ранее не работали с языком SQL, то можете пройти курс по основам SQL на Shultais Education.

Ну, а мы, научимся работать с сетями из Postgresql и для рассмотрим несколько несложных примеров. Представим, что у нас есть две таблицы: одна хранит IP-адреса компьютеров, которые обращались по сети к общедоступному принтеру, а вторая список подсетей в офисе. Наша задача – подсчитать количество обращений к принтеру из разных подсетей.

Подсчет адресов в сетях

Сперва создадим сами таблицы. Для хранения данных о сетях можно использовать следующий код:

CREATE TABLE IF NOT EXISTS network (
    id integer NOT NULL DEFAULT nextval('networks_id_seq'::regclass),
    name character varying(50),
    network_ip cidr,
    CONSTRAINT networks_pkey PRIMARY KEY (id)
);

Обратите внимание на столбец network_ip cidr. cidr — это специальный тип данных для хранения информации о сети. Он позволяет записывать как IP адрес, так и маску.

Заполним таблицу двумя сетями с помощью INSERT-запроса:

INSERT INTO networks (name, network_ip)
VALUES
    ('Офис 1', '192.168.13.0/25'),
    ('Офис 2', '192.168.13.128/25');

Это небольшие сети, каждая их которых может содержать до 126 устройств.

Теперь создадим таблицу для хранения IP-адресов, которые обращались к принтеру:

CREATE TABLE IF NOT EXISTS access_log (
    date timestamp with time zone NOT NULL DEFAULT now(),
    ip_address inet NOT NULL
);

На этот раз обратите внимание на тип данных inet – он нужен непосредственно для хранения IP-адресов (без маски). Заполним таблицу тестовыми данными:

INSERT INTO access_log (ip_address) 
VALUES
    ('192.168.13.133'),
    ('192.168.13.16'),
    ('192.168.13.230'),
    ('192.168.13.8'),
    ('192.168.13.109'),
    ('192.168.12.41'),
    ('192.168.13.33'),
    ('192.168.13.208'),
    ('192.168.13.139'),
    ('192.168.13.16'),
    ('192.168.13.57');

А теперь давайте определим к какой сети относится каждый из IP адресов. Нам поможет такой SQL-запрос:

SELECT
    date,
    ip_address,
    networks.name
FROM access_log
LEFT JOIN networks ON networks.network_ip >> ip_address;

Это по-настоящему удивительный JOIN, так как внутри, для соединения записей из двух таблиц, мы используем оператор >> (contains), который сразу проверяет находится ли ip_address в сети networks.network_ip.

После выполнения мы получим такую таблицу:

Обратите внимание, что один из адресов содержит NULL, так как он находится вне заданных сетей.

Далее посчитаем сколько обращений было из каждой сети. Тут уже потребуется группировка с функциями агрегации:

SELECT
     networks.name,
     COUNT(*)
FROM access_log
LEFT JOIN networks ON networks.network_ip >> ip_address
GROUP BY networks.name
ORDER BY networks.name;

Данный SQL запрос вернет следующую таблицу:

С основной задачей мы справились.

Прочие возможности

Теперь кратко рассмотрим, какие еще есть возможности у PostgreSQL для работы с сетями.

Попробуем отправить в сеть первого офиса широковещательное сообщение, чтобы его получили все компьютеры. Для этого достаточно к адресу сети применить функцию broadcast. Напишем такой SQL-запрос:

SELECT broadcast(network_ip) FROM networks WHERE name = 'Офис 1';

Получили 192.168.13.127/25 – теперь можно спокойно отправлять сообщение всем устройствам офиса.

Или давайте получим список всех доступных адресов в сети второго офиса? Тут нам поможет функция generate_series. Она позволяет генерировать последовательности в заданном диапазоне.

Во второй сети 126 доступных адресов, поэтому нам нужна серия чисел от 1 до 126 и оператор сложения, с помощью которого можно без ошибок увеличивать IP-адреса:

SELECT
    host('192.168.13.128/25')::inet + g AS ip_address
FROM generate_series(1, 126) g
ORDER BY ip_address;

После запуска мы получим такую таблицу (первые 6 записей):

Надеемся наша небольшая статья раскрыла вам возможности Postgresql для работы с сетями и если вы используете базы данных в вашей работе, то смело можете применять полученные знания на практике.

Понравилась статья? Поделиться с друзьями:
IPCalc Blog
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: