Vincoli di arco

Si applica a: SQL Server 2019 (15.x) e versioni successive Database SQL diIstanza gestita di SQL di Azure

I vincoli di arco possono essere usati per imporre l'integrità dei dati e semantica specifica per le tabelle archi nel database a grafo di SQL Server.

Vincoli di arco

Per impostazione predefinita, le tabelle edge non applicano alcun elemento per gli endpoint dell’edge. Questo significa che un arco in un database a grafo poteva connettere qualsiasi nodo a qualsiasi altro nodo, indipendentemente dal tipo.

Il grafo di SQL supporta i vincoli di arco, che consentono agli utenti di aggiungere vincoli alle tabelle archi, per imporre una semantica specifica e mantenere l'integrità dei dati. Quando si aggiunge un nuovo edge a una tabella edge con vincoli di arco, il Motore di database impone che i nodi a cui tenta di connettersi l'edge esistano nelle tabelle nodi appropriate. Viene inoltre garantito che un nodo non possa essere eliminato, se qualsiasi edge fa riferimento a quel nodo.

Clausole dei vincoli di arco

Un vincolo di arco singolo è costituito da una o più clausole.

CONSTRAINT constraint_name CONNECTION (cause1[, clause2...])
  • Una clausola vincolo di arco è una coppia di nomi di tabelle di nodo, separati dalla parola chiave TO.
  • Il primo nome della tabella nella clausola vincolo di arco è il nome della tabella del nodo FROM per la relazione perimetrale.
  • Il secondo nome della tabella nella clausola vincolo di arco è il nome della tabella del nodo TO per la relazione perimetrale.
  • La coppia di nomi di tabella indica quindi la direzione della relazione perimetrale.
  • Come indicato in precedenza, un vincolo di arco può contenere una o più clausole dei vincoli di arco.

Più vincoli e clausole

  • Vengono applicati più vincoli di arco, definiti per la stessa tabella archi, con un operatore AND.
  • Con un operatore vengono applicate più clausoleOR dei vincoli di arco definite all'interno dello stesso vincolo di arco.

Prendere in considerazione i Supplier nodi e Customer nel grafico. Ogni oggetto può essere correlato al nodo Product da una singola tabella archi condivisa: bought. La tabella archi bought supporta i tipi di relazione Customer-(bought)->Product e Supplier-(bought)->Product. Questa operazione può essere eseguita usando un singolo vincolo di arco con più clausole dei vincoli di arco.

Esempi
CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)

L'esempio precedente mostra un vincolo di arco, con una clausola vincolo di arco. Questo vincolo supporta Customer-(bought)->Product. Vale a dire, l'inserimento di una relazione perimetrale bought da un Customer a Product sarebbe consentito. Se si prova a inserire qualsiasi altra combinazione di nodi, ad esempio Supplier-(bought)->Product, anche se può descrivere una relazione valida nel mondo reale, avrebbe esito negativo.

CONSTRAINT EC_BOUGHT CONNECTION (Supplier TO Product, Customer TO Product)

L'esempio precedente mostra un vincolo di arco, con due clausole vincolo di arco. Queste clausole di vincolo consentono all'arco bought di contenere relazioni Supplier-(bought)->Product o Customer-(bought)->Product. L'inserimento di altri tipi di relazioni perimetrali nella tabella bought non riuscirebbe.

CONSTRAINT EC_BOUGHT1 CONNECTION (Supplier TO Product)
CONSTRAINT EC_BOUGHT2 CONNECTION (Customer TO Product)

L'esempio precedente mostra due vincoli nella stessa tabella archi, con ogni vincolo di arco che specifica una clausola di vincolo. In questa situazione, SQL consente solo gli inserimenti che soddisfano entrambe le clausole dei vincoli di arco contemporaneamente. Questa operazione non è attualmente possibile. Non esiste alcuna coppia di nodi in grado di soddisfare entrambe le clausole dei vincoli di edge. Questa combinazione di vincoli di arco rende non utilizzabile la tabella archi.

Per una spiegazione dettagliata della posizione in cui è possibile usare più vincoli di edge in uno scenario reale, vedere l'esempio "Creazione di un nuovo vincolo di edge nella tabella archi esistente, con una nuova clausola vincolo di edge" più avanti in questa pagina.

Indici sui vincoli di arco

La creazione di un vincolo di edge non determina automaticamente la creazione di un indice corrispondente sulle colonne $from_id e $to_id nella tabella edge. La creazione manuale di un indice per una coppia $from_id, $to_id è consigliata in presenza di query di ricerca di punti o carichi di lavoro OLTP.

Azioni referenziali ON DELETE sui vincoli di arco

Le azioni di propagazione su un vincolo di arco consentono agli utenti di definire la azioni eseguite dal motore di database quando un utente elimina il nodo o i nodi a cui si connette l'arco specificato. Le azioni referenziali seguenti possono essere definite: NESSUNA AZIONE Il motore di database genera un errore quando si tenta di eliminare un nodo con gli archi connessi.

CASCADE Quando si elimina un nodo dal database, vengono eliminati gli archi connessi.

Utilizzo di vincoli di edge

È possibile definire un vincolo di arco in SQL Server usando Transact-SQL. È possibile definire un vincolo di arco solo in una tabella archi del grafo. Per creare, eliminare o modificare un vincolo di arco, è necessario avere l'autorizzazione ALTER per la tabella.

Creare vincoli di arco

Gli esempi seguenti mostrano come creare un vincolo di arco in tabelle nuove o esistenti.

Creare un vincolo di arco in una nuova tabella edge

L'esempio seguente crea un vincolo di edge nella tabella edge bought.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      ,CustomerName VARCHAR(100)
   )
AS NODE;
GO
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      ,ProductName VARCHAR(100)
   )
AS NODE;
GO
CREATE TABLE bought
   (
      PurchaseCount INT
         ,CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product) ON DELETE NO ACTION
   )
   AS EDGE;

Definizione di azioni referenziali in una nuova tabella archi

Nell'esempio seguente viene creato un vincolo di arco nella tabella edge bought e viene definita l'azione referenziale ON DELETE CASCADE.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      ,CustomerName VARCHAR(100)
   )
AS NODE;
GO
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      ,ProductName VARCHAR(100)
   )
AS NODE;
GO
CREATE TABLE bought
   (
      PurchaseCount INT
         ,CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product) ON DELETE CASCADE
   )
   AS EDGE;

Aggiungere un vincolo di arco a una tabella edge esistente

L'esempio seguente usa ALTER TABLE per aggiungere un vincolo di edge nella tabella edge bought.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      , CustomerName VARCHAR(100)
   )
   AS NODE;
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      , ProductName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE bought
   (
      PurchaseCount INT
   )
   AS EDGE;
GO
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Customer TO Product);

Creare un nuovo vincolo di arco in una tabella archi esistente, con clausole aggiuntive per il vincolo di arco

L'esempio seguente usa il comando ALTER TABLE per aggiungere un nuovo vincolo di edge con clausole aggiuntive per il vincolo di edge nella tabella edge bought.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      , CustomerName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE Supplier
   (
      ID INTEGER PRIMARY KEY
      , SupplierName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      , ProductName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE bought
   (
      PurchaseCount INT
      , CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
   )
   AS EDGE;
-- Drop the existing edge constraint first and then create a new one.
ALTER TABLE bought DROP CONSTRAINT EC_BOUGHT;
GO
-- User ALTER TABLE to create a new edge constraint.
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Customer TO Product, Supplier TO Product);

Nell'esempio precedente sono presenti due clausole per il vincolo di arco nel vincolo EC_BOUGHT1, una che connette Customer a Product e l'altra che connette Supplier a Product. Entrambe queste clausole vengono applicate in disgiunzione. Vale a dire, un determinato arco deve soddisfare una delle due clausole per essere consentito nella tabella archi.

Creare un nuovo vincolo di edge in una tabella edge esistente, con una nuova clausola per il vincolo di edge

L'esempio seguente usa il comando ALTER TABLE per aggiungere un nuovo vincolo di edge con una nuova clausola per il vincolo di edge nella tabella edge bought.

-- CREATE node and edge tables
CREATE TABLE Customer
  (
     ID INTEGER PRIMARY KEY
     , CustomerName VARCHAR(100)
  )
  AS NODE;
GO
CREATE TABLE Supplier
  (
     ID INTEGER PRIMARY KEY
     , SupplierName VARCHAR(100)
  )
  AS NODE;
GO
CREATE TABLE Product
  (
     ID INTEGER PRIMARY KEY
     , ProductName VARCHAR(100)
  )
  AS NODE;
GO
CREATE TABLE bought
  (
     PurchaseCount INT,
        CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
  )
  AS EDGE;
GO

Nell'esempio precedente si supponga che ora sia necessario includere anche la relazione Supplier a Product, attraverso la tabella archi bought. È possibile provare ad aggiungere un nuovo vincolo di edge:

ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT1 CONNECTION (Supplier TO Product);

Tuttavia, l'aggiunta di un nuovo vincolo di edge non è la soluzione corretta. Abbiamo creato due vincoli edge separati sulla tabella edge bought, EC_BOUGHT e EC_BOUGHT1. Entrambi questi vincoli di arco hanno clausole diverse per il vincolo di arco. Se una tabella archi ha più di un vincolo di arco, un determinato arco deve soddisfare TUTTI i vincoli di arco per essere consentito nella tabella archi. Poiché nessun edge può soddisfare sia EC_BOUGHT che EC_BOUGHT1 qui, l'istruzione precedente ALTER TABLE ha esito negativo se sono presenti righe nella tabella edge bought acquistata.

Per creare correttamente questo vincolo di arco, il modo prescritto consiste nel seguire una sequenza simile alla seguente:

-- First, add the desired ("super-set") constraint:
ALTER TABLE bought ADD CONSTRAINT EC_BOUGHT_NEW CONNECTION (Customer TO Product, Supplier TO Product);
GO

-- Then, drop the older edge constraint:
ALTER TABLE bought DROP CONSTRAINT EC_BOUGHT;
GO

-- If needed, you can rename the new edge constraint to match the original name:
EXECUTE sp_rename '[dbo].[EC_BOUGHT_NEW]', '[dbo].[EC_BOUGHT]';

Il fatto che è stato aggiunto il nuovo vincolo "super set" senza eliminare quello precedente, consente all'operazione di essere un'operazione di soli metadati: non è necessario controllare tutti i dati esistenti nella tabella bought, poiché include il vincolo esistente.

Con questo, per essere consentito nella tabella edge bought, un determinato arco deve soddisfare una delle clausole nel vincolo EC_BOUGHT_NEW. Di conseguenza, qualsiasi edge che sta tentando di connettersi valido Customer a Product o Supplier ai Product nodi, è consentito.

Eliminare vincoli di arco

L'esempio seguente identifica prima di tutto il nome del vincolo di arco e quindi questo viene eliminato.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      , CustomerName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      , ProductName VARCHAR(100)
   ) AS NODE;
GO
CREATE TABLE bought
   (
      PurchaseCount INT
      , CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product)
    )
    AS EDGE;
GO

-- Return the name of edge constraint.
SELECT name
   FROM sys.edge_constraints
   WHERE type = 'EC' AND parent_object_id = OBJECT_ID('bought');
GO

-- Delete the primary key constraint.
ALTER TABLE bought
DROP CONSTRAINT EC_BOUGHT;

Modificare vincoli di arco

Per modificare un vincolo di edge usando Transact-SQL, è prima necessario eliminare il vincolo di edge esistente e quindi ricrearlo con la nuova definizione.

Visualizzare vincoli di arco

La visibilità dei metadati nelle viste del catalogo è limitata alle entità a protezione diretta di cui un utente è proprietario o a cui l'utente ha concesso alcune autorizzazioni. Per altre informazioni, vedere Metadata Visibility Configuration.

Nell'esempio vengono restituiti tutti i vincoli di edge e le relative proprietà per la tabella edge bought nel database tempdb.

-- CREATE node and edge tables
CREATE TABLE Customer
   (
      ID INTEGER PRIMARY KEY
      , CustomerName VARCHAR(100)
   )
   AS NODE;
GO
CREATE TABLE Supplier
   (
      ID INTEGER PRIMARY KEY
      , SupplierName VARCHAR(100)
   )
   AS NODE;
   GO
CREATE TABLE Product
   (
      ID INTEGER PRIMARY KEY
      , ProductName VARCHAR(100)
   )
   AS NODE;

-- CREATE edge table with edge constraints.
CREATE TABLE bought
   (
      PurchaseCount INT
      , CONSTRAINT EC_BOUGHT CONNECTION (Customer TO Product, Supplier TO Product)
   )
   AS EDGE;

-- Query sys.edge_constraints and sys.edge_constraint_clauses to view
-- edge constraint properties.
SELECT
   EC.name AS edge_constraint_name
   , OBJECT_NAME(EC.parent_object_id) AS edge_table_name
   , OBJECT_NAME(ECC.from_object_id) AS from_node_table_name
   , OBJECT_NAME(ECC.to_object_id) AS to_node_table_name
   , is_disabled
   , is_not_trusted
FROM sys.edge_constraints EC
   INNER JOIN sys.edge_constraint_clauses ECC
   ON EC.object_id = ECC.object_id
WHERE EC.parent_object_id = object_id('bought');

Passaggi successivi