Pracuję nad modelowaniem różnych aspektów sieci w bazie danych. Jednym z bardziej irytujących problemów, z którymi mamy do czynienia, jest tworzenie zakresów podsieci, a następnie ustalenie, czy dany zbiór adresów IP mieści się w tych zakresach. Nasz obecny model uwzględnia różnic między IPv4 i IPv6 z następującymi kolumnami:Biorąc pod uwagę zakres podsieci i listę adresów IP, zaznacz wszystkie wiersze, w których adresy IP mieszczą się między
[subnet_sk] [int] IDENTITY(1,1) NOT NULL,
[ipv6_network] [char](39) NULL,
[ipv6_broadcast] [char](39) NULL,
[ipv4_network] [char](15) NULL,
[ipv4_broadcast] [char](15) NULL,
[network_type] [char](4) NOT NULL
Powyższy schemat sprawia, że kilka założeń, które mają podkreślić. Wykorzystujemy w pełni rozwinięte adresy IP (192.168.001.001
vs. 192.168.1.1
) do przechowywania i porównywania. Podjęliśmy tę decyzję z powodu problemów związanych z przechowywaniem IPv6 addresses numerically in SQL server (bigints są niepodpisane, co oznacza, że musielibyśmy użyć sześciu kolumn do reprezentowania IPv6).
Biorąc pod uwagę ten schemat tabeli jest dość łatwe do napisania jednego OFF Wybierz sprawozdania do określenia, czy IP dowolnego typu jest między zakresami w tabeli:
select *
from subnet
where '1234:0000:0000:0000:fc12:00ab:0042:1050'
between ipv6_network
and ipv6_broadcast
-- or alternatively for IPv4
select *
from subnet
where '192.168.005.015'
between ipv4_network
and ipv4_broadcast
Co jest trudniejsze jest podana lista Adresy IP określają, które z nich znajdują się pomiędzy zakresami podsieci. Lista adresów IP zostanie dostarczona przez użytkownika i będzie przechowywana w bazie danych w postaci , a nie. Oczywiście dla danych przechowywanych w bazie danych mogę zrobić podobne sprzężenie jak w poniższym przykładzie. Na przykład użytkownik może podać 1234:0000:0000:0000:fc12:00ab:0042:1050
, 192.168.001.001
i 192.168.1.1
. Jedynym rozwiązaniem mam wymyślić jest użycie table-valued function to split a list adresów IP i wykonać za pomocą sprzężenia pomiędzy:
-- this only covers the IPv4 addresses from the above list a similar query would
-- be used for IPv6 and the two queries could be unioned
select sub.*
from fn_SplitList('192.168.001.001,192.168.005.015',',') split
join subnet sub
on split.Data
between sub.ipv4_network
and sub.ipv4_broadcast
przy wykorzystaniu funkcji podziału działa czuje hacky. Spędziłem większą część poranka wąchając około common table expressions, ale nie mogłem wymyślić implementacji, która by działała. Najlepiej by było gdyby jeden wybrał, czy odrzucić dany ciąg z kolumn IPv4 lub IPv6, ale jeśli to nie jest możliwe, mogę oddzielić listę przed przekazaniem kolekcji adresów IP do bazy danych.
Aby ułatwić odpowiedź, utworzyłem SQL Fiddle powyższych. Czy istnieje mechanizm w SQL (wolałbym nie używać T-SQL) z podaniem listy adresów IP, aby określić, które z istniejących zakresów podsieci znajdują się pomiędzy tymi adresami? Czy powyższy schemat jest nawet właściwym podejściem do problemu, gdyby inny model danych doprowadził do łatwiejszego rozwiązania?
nie mam dobrą znajomość sieci. Chciałbym wiedzieć, że tylko fn_SplitList() przeszkadza ci lub chcesz znaleźć lepszy sposób na obsłużenie całego scenariusza? –
@RaviSingh biorąc pod uwagę ten model danych miałbym to samo pytanie, gdybyśmy pracowali z listą dat, próbując ustalić, czy mieszczą się w zakresie. Więc moim problemem jest to, że czuję, że fn_SplitList jest sposobem obejścia problemu, ale wydaje się, że istnieje czystsze rozwiązanie. To powiedziawszy, jeśli powiesz mi "twój schemat jest błędny, a twoje zapytanie byłoby łatwiejsze, gdyby twój model danych był skonfigurowany w ten sposób," Byłbym wszystkimi uszami. Więc jeśli nie możesz pomóc w modelowaniu, ale możesz pomóc w lepszym zapytaniu, które nie używa fn_SplitList, jestem bardzo zainteresowany twoim rozwiązaniem. – ahsteele
Natknęliśmy się na to późno, ale dla odniesienia tutaj są niektóre podobne wątki omawiające podziały stringów w SQL Server: http://stackoverflow.com/questions/2647/split-string-in-sql i http://stackoverflow.com/ pytania/314824/t-sql-przeciwny-do-ciąg-konkatenacja-jak-podzielony-na-wiele-reco – rutter