Работа с 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 для работы с сетями и если вы используете базы данных в вашей работе, то смело можете применять полученные знания на практике.
