Использование SQL для определения значения cidr маски подсети

Я хотел бы найти способ выполнить SQL-запрос, который вычислит cidr (битовое представление) маски подсети, хранящейся в базе данных. Так, например, у меня есть 255.255.255.0 или его десятичное значение (4294967040), хранящееся в базе данных. Я хотел бы сделать выбор и вернуть / 24 представление через запрос.

Я сделал следующее, чтобы определить последний IP-адрес подсети, поэтому я надеюсь сделать что-то подобное, чтобы определить представление маски cidr.

select concat(inet_ntoa(ip_addr),'-',
    inet_ntoa(ip_addr+(POWER(2,32)-ip_mask-1))) range 
from subnets 
order by ip_addr

Желательно, чтобы это был оператор SQL, который работал бы под mysql, postgres, oracle и т. Д.


person Matt P    schedule 10.11.2008    source источник


Ответы (3)


Думаю, я нашел решение своей проблемы. Вот что я сделал:

select CONCAT(INET_NTOA(ip_addr),'/',32-log2((4294967296-ip_mask))) net 
from subnets 
order by ip_addr

Обычно я беру десятичную маску и вычитаю ее из максимального десятичного значения. Затем я ввожу log2 для этого значения, чтобы получить значение логарифма. Затем просто вычтите это из 32 (максимальный доступный бит).

Надеюсь, что это поможет другим.

Спасибо

person Matt P    schedule 30.12.2008
comment
Я проверил это по всем значениям в этой таблице и убедился, что они точны: kthx.at/subnetmask. - person apostl3pol; 13.09.2017

В запросах SQL нет конструкции процедурного цикла (несмотря на процедурный язык), но вы можете сравнить один набор строк с другим набором строк, что похоже на цикл.

У вас есть только 32 возможных маски подсети. В таких случаях имеет смысл создать небольшую таблицу, в которой будут храниться эти 32 маски и связанный номер CIDR.

CREATE TABLE cidr (
  bits INT UNSIGNED PRIMARY KEY,
  mask INT UNSIGNED NOT NULL
);

INSERT INTO cidr (bits) VALUES
  ( 1), ( 2), ( 3), ( 4), ( 5), ( 6), ( 7), ( 8), ( 9), (10),
  (11), (12), (13), (14), (15), (16), (17), (18), (19), (20),
  (21), (22), (23), (24), (25), (26), (27), (28), (29), (30),
  (31), (32);

UPDATE cidr SET mask = ((POWER(2,32)-1)<<(32-bits)) & (POWER(2,32)-1);

SELECT CONCAT(s.ip_addr, '/', c.bits)
FROM cidr c JOIN subnets s ON (c.mask = inet_aton(s.ip_mask));
person Bill Karwin    schedule 11.11.2008
comment
Я надеялся избежать добавления стола. Я надеялся, что можно будет провести дальнейшие математические вычисления, чтобы преобразовать десятичное в двоичное и затем подсчитать биты. Спасибо, это было полезно - person Matt P; 12.11.2008

например вам нужно преобразовать 255.255.255.252 маску сети в битовую маску.

Я всегда использую этот простой запрос (PostgreSQL):

SELECT 32-length(trim(((split_part('255.255.255.252','.',1)::bigint*(256^3)::bigint +
                        split_part('255.255.255.252','.',2)::bigint*(256^2)::bigint +
                        split_part('255.255.255.252','.',3)::bigint*256 +
                        split_part('255.255.255.252','.',4)::bigint)::bit(32))::text,'1'));

не так красиво, как могло бы быть, но оно короткое и работает как шарм ..

person Michael Kaška    schedule 16.02.2016