Primär- und Fremdschlüsseleinschränkungen

Gilt für: SQL Server 2016 (13.x) und spätere Versionen Azure SQL-DatenbankAzure SQL Managed InstanceSQL database in Microsoft Fabric

Primärschlüssel und Fremdschlüssel sind zwei Typen von Einschränkungen, die zum Erzwingen der Datenintegrität in SQL Server-Tabellen verwendet werden können. Diese sind wichtige Datenbankobjekte.

Primärschlüssel-Einschränkungen

Eine Tabelle verfügt normalerweise über eine Spalte oder eine Kombination aus Spalten, die Werte enthalten, die jede Zeile in der Tabelle eindeutig identifizieren. Diese Spalte oder Kombination aus Spalten wird als Primärschlüssel (PK, Primary Key) der Tabelle bezeichnet und erzwingt die Entitätsintegrität der Tabelle. Da Primärschlüssel-Einschränkungen eindeutige Daten garantieren, werden sie häufig für eine Identitätsspalte definiert.

Wenn Sie eine Primärschlüssel-Einschränkung für eine Tabelle angeben, erzwingt die Datenbank-Engine die Eindeutigkeit der Daten, indem automatisch ein eindeutiger Index für die Primärschlüsselspalten erstellt wird. Der Index ermöglicht darüber hinaus den schnellen Zugriff auf Daten, wenn der Primärschlüssel in Abfragen verwendet wird. Wenn eine Primärschlüssel-Einschränkung für mehrere Spalten definiert wird, können Werte innerhalb einer Spalte dupliziert werden; jede Kombination aus den Werten aller Spalten, die in der Definition der PRIMARY KEY-Einschränkung enthalten sind, muss jedoch eindeutig sein.

Wie in der folgenden Abbildung gezeigt, bilden die ProductID- und VendorID-Spalten der Tabelle Purchasing.ProductVendor eine zusammengesetzte Primärschlüsseleinschränkung für diese Tabelle. Dadurch wird sichergestellt, dass jede Zeile in der Tabelle ProductVendor über eine eindeutige Kombination von ProductID und VendorID verfügt. Dies verhindert die Einfügung doppelter Zeilen.

Diagramm von Zeilen in einer Tabelle für eine zusammengesetzte PRIMARY KEY-Einschränkung.

  • Eine Tabelle kann nur eine Primärschlüsselbedingung enthalten.
  • Ein Primärschlüssel darf 32 Spalten und eine Gesamtlänge von 900 Bytes nicht überschreiten.
  • Der durch eine Primäerschlüssel-Einschränkung generierte Index kann nicht dazu führen, dass die Anzahl der Indizes der Tabelle 999 nicht gruppierte Indizes und 1 gruppierten Index übersteigt.
  • Wenn für eine Primärschlüsseleinschränkung kein gruppierter bzw. nichtgruppierter Index angegeben ist, wird ein gruppierter Index verwendet, sofern auf der Tabelle kein gruppierter Index vorhanden ist.
  • Alle Spalten, die in einer Primärschlüsselbedingung definiert sind, müssen als NOT NULL definiert sein. Wenn keine Nullfähigkeit angegeben ist, wird für alle Spalten, die an einer Primärschlüsselbedingung beteiligt sind, die Nullfähigkeit auf NOT NULL festgelegt.
  • Wenn ein Primärschlüssel für eine Spalte eines CLR-benutzerdefinierten Typs definiert wird, muss die Implementierung des Typs eine binäre Sortierreihenfolge unterstützen.

Fremdschlüsseleinschränkungen

Ein Fremdschlüssel (FS) ist eine Spalte oder eine Kombination von Spalten, mit deren Hilfe eine Verknüpfung zwischen den Daten in zwei Tabellen eingerichtet und erzwungen wird, um die Daten zu steuern, die in der Fremdschlüsseltabelle gespeichert werden können. In einem Fremdschlüsselverweis wird zwischen zwei Tabellen ein Link erstellt, wenn eine Spalte bzw. mehrere Spalten einer Tabelle auf die Spalte bzw. Spalten mit dem Primärschlüsselwert einer anderen Tabelle verweisen. Diese Spalte wird zu einem Fremdschlüssel in der zweiten Tabelle.

Die Tabelle Sales.SalesOrderHeader verfügt beispielsweise über einen Fremdschlüssellink zur Tabelle Sales.SalesPerson, da eine logische Beziehung zwischen Verkaufsaufträgen und Vertriebsmitarbeiter*innen besteht. Die Spalte SalesPersonID in der Tabelle SalesOrderHeader entspricht der Primärschlüsselspalte in der Tabelle SalesPerson. Die Spalte SalesPersonID in der Tabelle SalesOrderHeader ist der Fremdschlüssel für die Tabelle SalesPerson. Durch das Erstellen dieser Fremdschlüsselbeziehung kann ein Wert für SalesPersonID nicht in die Tabelle SalesOrderHeader eingefügt werden, wenn er noch nicht in der Tabelle SalesPerson vorhanden ist.

Eine Tabelle kann auf maximal 253 andere Tabellen und Spalten als Fremdschlüssel (ausgehende Referenzen) verweisen. SQL Server 2016 (13.x) erhöht den Grenzwert für die Anzahl der anderen Tabellen und Spalten, die auf Spalten in einer einzelnen Tabelle (eingehende Referenzen) verweisen können, von 253 auf 10.000. (Kompatibilitätsgrad 130 oder höher erforderlich.) Für die Erhöhung gelten folgende Einschränkungen:

  • Mehr als 253 Fremdschlüsselverweise werden nur für DELETE DML-Operationen unterstützt. UPDATE- und MERGE-Vorgänge werden nicht unterstützt.

  • Auch eine Tabelle mit einem Fremdschlüsselverweis auf sich selbst ist auf 253 Fremdschlüsselverweise beschränkt.

  • Mehr als 253 Fremdschlüsselverweise werden derzeit für Columnstore-Indizes, speicheroptimierte Tabellen, Stretch Database oder partitionierte Fremdschlüsseltabellen nicht unterstützt.

    Important

    Stretch Database ist in SQL Server 2022 (16.x) und der Azure SQL-Datenbank veraltet. Diese Funktion wird in einer zukünftigen Version der Datenbank-Engine entfernt. Nutzen Sie diese Funktionen bei Neuentwicklungen nicht mehr, und planen Sie die Änderung von Anwendungen, die diese Funktion zurzeit verwenden.

Indizes für Fremdschlüsseleinschränkungen

Im Gegensatz zu Primärschlüsselbeschränkungen wird beim Erstellen einer Fremdschlüsselbeschränkung nicht automatisch ein entsprechender Index erstellt. Das manuelle Erstellen eines Indexes für einen Fremdschlüssel empfiehlt sich jedoch aus folgenden Gründen:

  • Fremdschlüsselspalten werden häufig in Join-Kriterien verwendet, wenn Daten aus verknüpften Tabellen in Abfragen kombiniert werden, indem die Spalte oder Spalten in der Fremdschlüsseleinschränkung einer Tabelle mit der Primärschlüssel- oder eindeutigen Schlüsselspalte bzw. den entsprechenden Spalten der anderen Tabelle abgeglichen werden. Ein Index ermöglicht es der Datenbank-Engine, die verbundenen Daten in der Fremdschlüsseltabelle schnell zu finden. Es ist jedoch nicht zwingend erforderlich, einen Index zu erstellen. Daten aus zwei zusammengehörigen Tabellen können auch dann kombiniert werden, wenn zwischen den Tabellen keine Primärschlüssel- oder Fremdschlüsseleinschränkungen definiert sind. Eine Fremdschlüsselbeziehung zwischen zwei Tabellen weist jedoch darauf hin, dass die beiden Tabellen so optimiert wurden, dass sie in einer Abfrage kombiniert werden können, bei der die Schlüssel als Kriterien verwendet werden.

  • Änderungen an Primary-Key-Constraints werden anhand von Foreign-Key-Constraints in zugehörigen Tabellen überprüft.

Referentielle Integrität

Eine FOREIGN KEY-Einschränkung dient zwar in erster Linie zur Kontrolle der Daten, die in der Fremdschlüsseltabelle gespeichert werden können; sie kontrolliert jedoch auch die Änderungen, die an Daten in der Primärschlüsseltabelle vorgenommen werden. Wenn beispielsweise die Zeile für eine*n Vertriebsmitarbeiter*in aus der Tabelle Sales.SalesPerson gelöscht wird und die ID des Vertriebsmitarbeiters bzw. der Vertriebsmitarbeiterin in der Tabelle Sales.SalesOrderHeader für Verkaufsaufträge verwendet wird, ist die relationale Integrität zwischen den beiden Tabellen beschädigt. Die Verkaufsaufträge des gelöschten Vertriebsmitarbeiters bzw. der gelöschten Vertriebsmitarbeiterin sind in der Tabelle SalesOrderHeader verweist, ohne dass ein Link zu den Daten in der Tabelle SalesPerson besteht.

Eine Fremdschlüsselbeschränkung verhindert diese Situation. Die Einschränkung erzwingt die referenzielle Integrität, indem sichergestellt wird, dass Änderungen an Daten in der Primärschlüsseltabelle nicht möglich sind, wenn diese Änderungen dazu führen, dass der Link zu Daten in der Fremdschlüsseltabelle ungültig wird. Wird ein Versuch unternommen, eine Zeile in einer Primärschlüsseltabelle zu löschen oder einen Primärschlüsselwert zu ändern, erzeugt diese Aktion einen Fehler, wenn der gelöschte oder geänderte Primärschlüsselwert einem Wert in der Fremdschlüssel-Einschränkung einer anderen Tabelle entspricht. Um eine Zeile in einer FOREIGN KEY-Einschränkung erfolgreich ändern oder löschen zu können, müssen Sie zuerst die Fremdschlüsseldaten in der Fremdschlüsseltabelle entweder löschen oder so ändern, dass der Fremdschlüssel mit anderen Primärschlüsseldaten verknüpft ist.

Kaskadierte referenzielle Integrität

Mithilfe von kaskadierenden Einschränkungen der referenziellen Integrität können Sie die Aktionen festlegen, die die Datenbank-Engine ausführt, wenn ein Benutzer versucht, einen Schlüssel zu löschen oder zu aktualisieren, auf den vorhandene Fremdschlüssel verweisen. Die folgenden kaskadierenden Aktionen können definiert werden.

  • NO ACTION

    Die Datenbank-Engine meldet einen Fehler, und die Lösch- oder Aktualisierungsaktion für die Zeile in der übergeordneten Tabelle wird zurückgesetzt.

  • CASCADE

    Wenn diese Zeile in der übergeordneten Tabelle aktualisiert oder gelöscht wird, werden die entsprechenden Zeilen in der verweisenden Tabelle aktualisiert oder gelöscht. CASCADE kann nicht angegeben werden, wenn eine timestamp-Spalte Teil eines Fremdschlüssels oder des Schlüssels ist, auf den verwiesen wird. ON DELETE CASCADE kann für eine Tabelle, die über einen INSTEAD OF DELETE-Trigger verfügt, nicht angegeben werden. ON UPDATE CASCADE kann nicht für Tabellen angegeben werden, die INSTEAD OF UPDATE-Trigger aufweisen.

  • SET NULL

    Alle Werte, aus denen sich der Fremdschlüssel zusammensetzt, werden auf NULL festgelegt, wenn die entsprechende Zeile in der übergeordneten Tabelle aktualisiert oder gelöscht wird. Damit diese Constraint ausgeführt werden kann, müssen die Fremdschlüsselspalten NULL-Werte zulassen. Diese Option kann nicht für Tabellen angegeben werden, die INSTEAD OF UPDATE-Trigger aufweisen.

  • SET DEFAULT

    Alle Werte, aus denen sich der Fremdschlüssel zusammensetzt, werden auf ihre Standardwerte festgelegt, wenn die entsprechende Zeile in der übergeordneten Tabelle aktualisiert oder gelöscht wird. Alle Fremdschlüsselspalten müssen Standarddefinitionen aufweisen, damit diese Einschränkung ausgeführt wird. Wenn eine Spalte Null-Werte zulässt, und es ist kein expliziter Standardwert festgelegt, wird NULL als der implizite Standardwert für die Spalte verwendet. Diese Option kann nicht für Tabellen angegeben werden, die INSTEAD OF UPDATE-Trigger aufweisen.

CASCADE, SET NULL, SET DEFAULT und NO ACTION können für Tabellen kombiniert werden, die referenzielle Beziehungen untereinander aufweisen. Wenn die Datenbank-Engine auf NO ACTION stößt, hält sie an und macht zugehörige CASCADE-, SET NULL- und SET DEFAULT-Aktionen rückgängig. Wenn eine DELETE-Anweisung eine Kombination aus CASCADE-, SET NULL-, SET DEFAULT- oder NO ACTION-Aktionen verursacht, werden alle CASCADE-, SET NULL- und SET DEFAULT-Aktionen angewendet, bevor die Datenbank-Engine auf eine beliebige NO ACTION prüft.

Trigger und kaskadierende referenzielle Aktionen

Kaskadierende referenzielle Aktionen lösen AFTER UPDATE oder AFTER DELETE-Trigger in der folgenden Weise aus:

  • Alle kaskadierenden referenziellen Aktionen, die direkt von der ursprünglichen DELETE oder UPDATE-Anweisung ausgelöst werden, werden zuerst ausgeführt.

  • Wenn für die betroffenen Tabellen AFTER-Trigger definiert wurden, werden diese Trigger ausgelöst, nachdem alle kaskadierenden Aktionen ausgeführt wurden. Diese Trigger werden in der entgegengesetzten Reihenfolge zur kaskadierenden Aktion ausgelöst. Falls es mehrere Trigger für eine einzelne Tabelle gibt, werden diese in zufälliger Reihenfolge ausgelöst, sofern es für die Tabelle nicht einen dedizierten ersten oder letzten Trigger gibt. Diese Reihenfolge wird mithilfe von sp_settriggerorderangegeben.

  • Wenn mehrere kaskadierende Ketten ihren Ursprung in der Tabelle haben, die das direkte Ziel der UPDATE oder DELETE-Aktion war, wird die Reihenfolge, in der diese Ketten ihre jeweiligen Trigger auslösen, nicht angegeben. Allerdings löst eine Kette immer erst alle ihre Trigger aus, bevor eine andere Kette ausgelöst wird.

  • Ein AFTER-Trigger für die Tabelle, die das direkte Ziel einer UPDATE- oder DELETE-Aktion ist, wird unabhängig davon ausgelöst, ob davon irgendwelche Zeilen betroffen sind oder nicht. In diesem Fall sind keine weiteren Tabellen von der Kaskadierung betroffen.

  • Wenn einer der vorherigen Trigger UPDATE- oder DELETE-Vorgänge für andere Tabellen ausführt, können diese Aktionen sekundäre kaskadierende Ketten starten. Die Verarbeitung dieser sekundären Ketten erfolgt für jede UPDATE- oder DELETE-Operation zu einem Zeitpunkt, nachdem alle Trigger für alle primären Ketten ausgelöst wurden. Dieser Prozess kann für alle nachfolgenden UPDATE oder DELETE-Operationen rekursiv wiederholt werden.

  • Die Ausführung von CREATE, ALTER, DELETE oder anderen DDL-Vorgängen innerhalb von Triggern kann dazu führen, dass DDL-Trigger ausgelöst werden. Dies kann anschließend DELETE oder UPDATE Vorgänge ausführen, die zusätzliche Kaskaden und Trigger starten.

  • Wenn innerhalb einer bestimmten kaskadierenden referenziellen Aktionskette ein Fehler generiert wird, wird ein Fehler ausgelöst, in dieser Kette werden keine AFTER Trigger ausgelöst, und der DELETEUPDATE Vorgang, der die Kette erstellt hat, wird zurückgesetzt.

  • Eine Tabelle mit einem INSTEAD OF-Trigger kann nicht gleichzeitig eine REFERENCES-Klausel aufweisen, die eine kaskadierende Aktion angibt. Ein AFTER-Trigger in einer Tabelle, die das Ziel einer kaskadierenden Aktion ist, kann jedoch eine INSERT, UPDATE oder DELETE-Anweisung in einer anderen Tabelle oder Sicht ausführen, die einen für dieses Objekt definierten INSTEAD OF-Trigger auslöst.