Graph Database
Eintrag zuletzt aktualisiert am: 24.05.2022
Mit SQL Server 2017 führt Microsoft neue Tabellentypen ein. Neben relationalen Tabellen unterstützt die neue Version jetzt Node- und Edge-Tabellen zur Erstellung von gerichteten Graphen mit Knoten und Kanten. Wie Listing 1 zeigt, legt man den Tabellentyp bei CREATE TABLE nach dem Schlüsselwort AS fast. Das Beispiel legt zwei Knotentabellen ("Firma" und "Person") sowie eine Kantentabelle "ArbeitetBei" an und fügt Beispieldatensätze ein. Wie man im Listing sieht, ist die Kantentabelle nicht auf bestimmte Knotentabellen geprägt, d.h. anders als eine relationale Zwischentabelle kann die Kantentabelle beliebige Beziehungen aufnehmen.
Eine Kantentabelle kann eigene Eigenschaften besitzen, wie man im Listing 1 bei der Kantentabelle "ArbeitetBei" mit Eigenschaft "Funktion" sieht. Knoten- und Kanten-Tabelle können neben relationalen Tabellen in einer SQL Server-
Datenbank koexistieren; das
SQL Server Management Studio zeigt sie in dem getrennten Ast "Graph Tables" an. Die Graph-Tabellen haben neben den vom Ersteller vergebenen Spalten weitere systemvergebene Spalten wie graph
id, $edge_id und $node_id. Die Spalte $nodeid kommt bei der Erstellung einer Beziehung zum Einsatz, wie Listing 1 bei den INSERT-Befehlen zeigt. In Listing 2 sieht man einige Abfragen auf diesem Graph-Beispiel mit dem neuen Match()-Operator. Der Match-Operator kann allerdings ausschließlich mit Graph-Tabellen, nicht aber mit relationalen Tabellen eingesetzt werden.
Bisher konnte man komplexe n:m-Beziehungen nur über relationale Zwischentabellen modellieren. Die Graph-Tabellen vereinfachen komplexere Abfragen über solche Beziehungen. In SQL Server 2017 können Knoten- und Kantentabellen noch nicht als Hauptspeicher-Tabelle, temporale Tabelle oder Polybase-Tabelle angelegt werden. Bestehende relationale Tabellen kann der Nutzer nicht in Knoten- oder Kantentabellen umwandeln. Das Entwicklungsteam plant laut [
https://blogs.technet.microsoft.com/dataplatforminsider/2017/04/20/graph-data-processing-with-sql-server-2017/], in Folgeversionen einige dieser Funktionen nachzurüsten.
Listing 1: Anlegen von zwei Knoten- und einer Kantentabelle mit entsprechenden Datensätzen
-- Knoten-Tabellen anlegen
CREATE TABLE [dbo].Firma(
ID [int] NOT NULL,
Firmenname [varchar](100) NULL,
Stadt [varchar](50) NULL
CONSTRAINT PK_Firma PRIMARY KEY (ID)
)
AS NODE;
CREATE TABLE [dbo].Person(
[ID] [int] NOT NULL,
[name] [varchar](100) NULL,
CONSTRAINT PK_Person PRIMARY KEY (ID)
) As Node;
GO
-- Kanten-Tabelle anlegen
CREATE TABLE [ArbeitetBei] (Funktion [varchar](50) )AS EDGE
-- Datensätze für Knoten-Tabellen
INSERT INTO Firma VALUES (1,'www.IT-Visions.de','Essen')
INSERT INTO Firma VALUES (2,'5Minds IT-Solutions Gmbh & Co KG','Gelsenkirchen')
INSERT INTO Person VALUES (10,'
Dr. Holger Schwichtenberg')
INSERT INTO Person VALUES (11,'Martin Möllenbeck')
INSERT INTO Person VALUES (12,'Björn Röber')
INSERT INTO Person VALUES (13,'Nicole Jones')
INSERT INTO Person VALUES (20,'Antje Kluth')
-- Datensätze für Kanten-Tabelle
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 10),
(SELECT $
node_id FROM Firma WHERE id = 1),
'Berater und Trainer');
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 10),
(SELECT $
node_id FROM Firma WHERE id = 2),
'Entwicklungsprojektleiter');
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 11),
(SELECT $
node_id FROM Firma WHERE id = 2),
'Geschäftsführer');
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 12),
(SELECT $
node_id FROM Firma WHERE id = 2),
'Geschäftsführer');
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 13),
(SELECT $
node_id FROM Firma WHERE id = 2),
'Geschäftsführer');
INSERT INTO [ArbeitetBei] VALUES
((SELECT $
node_id FROM Person WHERE id = 20),
(SELECT $
node_id FROM Firma WHERE id = 1),
'Büroleiterin');
Listing 2: Abfragen mit dem Match-Operator
-- Ausgabe aller Beziehungen
select * from [ArbeitetBei]
-- Abfrage: Alle Mitarbeiter einer Firma
SELECT f.Firmenname, p.name, ArbeitetBei.funktion FROM Person p, ArbeitetBei, Firma f
WHERE
MATCH(p-(ArbeitetBei)->f) and f.firmenname like '5Minds%'
-- Abfrage: Alle Firmen, bei der eine Person arbeitet
SELECT p.name, ArbeitetBei.funktion, f.firmenname FROM Person p, ArbeitetBei, Firma f
WHERE
MATCH(p-(ArbeitetBei)->f) and p.name like '%Schwichtenberg%'
-- Abfrage: Alle Firmen, bei der eine Person arbeitet (alternative Schreibweise)
SELECT p.name, a.funktion, f.firmenname FROM Person p, ArbeitetBei a, Firma f
WHERE
MATCH(f<-(a)-p) and p.name like '%Schwichtenberg%'
--- Alle Arbeitskollegen einer Person bei allen Firmen
SELECT p2.name, a2.funktion, f.firmenname FROM Person p1, person p2, ArbeitetBei a1, ArbeitetBei a2,Firma f
WHERE
MATCH(p1-(a1)->f<-(a2)-p2) and p1.name like '%Schwichtenberg%' and p2.name not like '%Schwichtenberg%'