MSSQL Substring
Hallo,
heute habe ich folgende Hearusforderung:
Tabelle1 (Netzwerkbereichsdefintionen)
Tabelle 2 (Geräteliste)
Ziel nun in SQL: gib mir Gerätenamen und Netzwerkname der Geräte aus, welche sich im gleichen Netz befinden.
Es sollte also wie folgt aussehen im Resultat:
Jetzt habe ich aber gerade eine Barrikade im Kopf, bin auch nicht so Deep-Dive SQL-Spezi. Hier mal mein Ansatz:
Wo ich jetzt komplett im Kopf fest hänge:
Wie gesagt, komplett irgendwie im Kopf verrant gerade dabei, eventuell sehe ich den Wald vor Bäumen nicht. Daher danke für jegliche Unterstützung beim Baumfällen
F.
heute habe ich folgende Hearusforderung:
Tabelle1 (Netzwerkbereichsdefintionen)
Ip-Bereiche | Name |
---|---|
192.168.0.0/24 | Standardnetz |
10.27.0.0/16 | Servernetz |
172.16.4.0/24 | DMZ |
Tabelle 2 (Geräteliste)
Gerätename | IP-Adresse |
---|---|
Server1 | 192.168.0.16 |
Server2 | 10.27.0.12 |
Server3 | 172.16.4.4 |
Server4 | 10.27.0.13 |
Ziel nun in SQL: gib mir Gerätenamen und Netzwerkname der Geräte aus, welche sich im gleichen Netz befinden.
Es sollte also wie folgt aussehen im Resultat:
Netzwerkname | Gerätename |
---|---|
Standardnetz | Server1 |
Servernetz | Server2 |
Servernetz | Server4 |
DMZ | Server3 |
Jetzt habe ich aber gerade eine Barrikade im Kopf, bin auch nicht so Deep-Dive SQL-Spezi. Hier mal mein Ansatz:
Select
Table01.Spalte2 AS NetzwerkName
,Table2.Spalte1 AS Gerätename
FROM
Table1 TAB1 LEFT JOIN Table2 TAB2
ON TAB1.Spalte1 =** //???//**
Wo ich jetzt komplett im Kopf fest hänge:
- Ich müsste jetzt eine Unterabfrage bauen, in welchem ich teile des Netzwerkbereiches gegen die IP des Geräte vergleiche.
- Problem: die Schreibweise der IP-Adressen, ich muss ausschliessen das jemand "010.027.x.x" schreibt anstelle "10.27..x.x" (volle IPSchreibweise vs. Kurzform)
- Sicherlich Substring's, aber wie kombinieren?
- als Trennkriterium könnte man in Tabelle 1 Spalte 1 die Punkte oder den Slash nutzen (also /24) z.b. aber wie am besten
- Im Join vergleichen: was gegen was
Wie gesagt, komplett irgendwie im Kopf verrant gerade dabei, eventuell sehe ich den Wald vor Bäumen nicht. Daher danke für jegliche Unterstützung beim Baumfällen
F.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 576189
Url: https://administrator.de/contentid/576189
Ausgedruckt am: 19.11.2024 um 09:11 Uhr
6 Kommentare
Neuester Kommentar
Moin,
kurzte Frage:
welches DBMS ist im EInsatz, auch welche Version.
Mit den Angaben kann man gezielter helfen...
€dit:
bei MS SQL gibt es die Funktion PARSENAME().
Schaue dir die einmal an:
https://docs.microsoft.com/de-de/sql/t-sql/functions/parsename-transact- ...
https://stackoverflow.com/questions/33717815/how-to-compare-ip-addresses ...
€dit2:
RegEx wäre auch ggf. eine Möglichkeit:
https://www.sqlshack.com/t-sql-regex-commands-in-sql-server/
Gruß
em-pie
kurzte Frage:
welches DBMS ist im EInsatz, auch welche Version.
- MS SQL 2008R2 fehlen Beispielsweise ggü. MS SQL 2012 manche integrierten Funktionen.
- mySQL ist dann an manchen Stellen noch mal ganz anders.
- 'ne DB2 kennt z.B. kein CONCAT()
Mit den Angaben kann man gezielter helfen...
€dit:
bei MS SQL gibt es die Funktion PARSENAME().
Schaue dir die einmal an:
https://docs.microsoft.com/de-de/sql/t-sql/functions/parsename-transact- ...
https://stackoverflow.com/questions/33717815/how-to-compare-ip-addresses ...
€dit2:
RegEx wäre auch ggf. eine Möglichkeit:
https://www.sqlshack.com/t-sql-regex-commands-in-sql-server/
Gruß
em-pie
Zitat von @DocuSnap-Dude:
Jepp, Substring habe ich bemerkt wird zu üppig und wirr. Daher halt mein Balken vor dem Kopf .
Jepp, Substring habe ich bemerkt wird zu üppig und wirr. Daher halt mein Balken vor dem Kopf .
Ich muss zugeben ich habe das unterschätzt, eine in meinem Kopf erstmal total elegante Lösung führt zu, sagen wir, einer show of force in Sachen SQL mit cte, xml, cross apply und irgendwas was ich selbst noch nichtmal checke mir aber binäre Ziffern liefert. Das in einem Abwasch zu "joinen" geht nicht wenn man da noch durchblicken will, daher habe ich eine Funktion gebaut.
CREATE FUNCTION dbo.test_convert_ipv4(@ipv4cidr_decimal VARCHAR(18))
RETURNS @t TABLE (
ipv4_binary VARCHAR(32),
ipv4_binary_net VARCHAR(32),
ipv4_binary_host VARCHAR(32),
ipv4cidr_decimal_net SMALLINT
)
AS
BEGIN
DECLARE @ipv4cidr_decimal_net SMALLINT,
@ipv4_decimal VARCHAR(15)
IF @ipv4cidr_decimal LIKE '%/%'
BEGIN
SET @ipv4_decimal = left(@ipv4cidr_decimal,charindex('/',@ipv4cidr_decimal)-1) + '.'
SET @ipv4cidr_decimal_net = convert(SMALLINT,right(@ipv4cidr_decimal,charindex('/',reverse(@ipv4cidr_decimal))-1))
END
ELSE
BEGIN
SET @ipv4_decimal = @ipv4cidr_decimal + '.'
END;
WITH cte(ipv4,octet,number) AS (
SELECT right(@ipv4_decimal,datalength(@ipv4_decimal)-charindex('.',@ipv4_decimal)),
left(@ipv4_decimal,charindex('.',@ipv4_decimal)-1),
1
UNION ALL
SELECT right(ipv4,datalength(ipv4)-charindex('.',ipv4)),
left(ipv4,charindex('.',ipv4)-1),
number + 1
FROM cte
WHERE number <= 3
)
INSERT INTO @t(ipv4_binary)
SELECT stuff(( SELECT ( CASE convert(INT,octet) & 128 WHEN 128 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 64 WHEN 64 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 32 WHEN 32 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 16 WHEN 16 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 8 WHEN 8 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 4 WHEN 4 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 2 WHEN 2 THEN '1' ELSE '0' END ) +
( CASE convert(INT,octet) & 1 WHEN 1 THEN '1' ELSE '0' END )
FROM cte
ORDER BY number
FOR XML PATH (''))
,1,1,'')
IF @ipv4cidr_decimal_net IS NOT NULL
BEGIN
UPDATE @t
SET ipv4_binary_net = left(ipv4_binary,@ipv4cidr_decimal_net),
ipv4_binary_host = right(ipv4_binary,32-@ipv4cidr_decimal_net),
ipv4cidr_decimal_net = @ipv4cidr_decimal_net
END
RETURN;
END
Mit der Funktion lassen sich deine Testdaten erweitern und dann gegeneinander abgleichen:
WITH Netzwerkbereichsdefintionen(IP_Bereich,Name) AS (
SELECT '192.168.0.0/24','Standardnetz' UNION ALL
SELECT '10.27.0.0/16','Servernetz' UNION ALL
SELECT '172.16.4.0/24','DMZ'
), Geräteliste(Gerätename,IP_Adresse) AS (
SELECT 'Server1','192.168.0.16' UNION ALL
SELECT 'Server2','10.27.0.12' UNION ALL
SELECT 'Server3','172.16.4.4' UNION ALL
SELECT 'Server4','10.27.0.13'
), Netzwerkbereichsdefintionen_erweitert(IP_Bereich,Name,ipv4_binary_net,ipv4cidr_decimal_net) AS (
SELECT IP_Bereich,Name,ipv4_binary_net,ipv4cidr_decimal_net
FROM Netzwerkbereichsdefintionen
CROSS APPLY dbo.test_convert_ipv4(IP_Bereich)
), Geräteliste_erweitert(IP_Adresse,Gerätename,ipv4_binary) AS (
SELECT IP_Adresse,Gerätename,ipv4_binary
FROM Geräteliste
CROSS APPLY dbo.test_convert_ipv4(IP_Adresse)
)
SELECT *
FROM Netzwerkbereichsdefintionen_erweitert nets
LEFT JOIN Geräteliste_erweitert hosts
ON nets.ipv4_binary_net = left(hosts.ipv4_binary,nets.ipv4cidr_decimal_net)