Die Verwendung mehrerer Fremdschlüssel in derselben Spalte in SQL Server

10

Mit SQL Server kann ich mehrere Fremdschlüssel in einer Spalte erstellen und jedes Mal, wenn ich nur einen anderen Namen verwende, einen anderen Schlüssel erstellen, der auf dasselbe Objekt verweist. Grundsätzlich definieren alle Schlüssel dieselbe Beziehung. Ich möchte wissen, was es nützt, mehrere Fremdschlüssel zu haben, die in derselben Spalte definiert sind und auf dieselbe Spalte in einer anderen Tabelle verweisen. Was ist der Vorteil davon, dass wir mit SQL Server so etwas tun können?

Geben Sie hier die Bildbeschreibung ein

igelr
quelle

Antworten:

12

Redundante Einschränkungen, die sich nur durch den Namen unterscheiden, haben keinen Vorteil. Ebenso hat es keinen Vorteil, redundante Indizes zu haben, die sich nur durch den Namen unterscheiden. Beide erhöhen den Overhead ohne Wert.

Das SQL Server-Datenbankmodul hindert Sie nicht daran. Gute Konventionen für die Benennung von Einschränkungen (z. B. FK_ReferencingTable_ReferencedTable) können zum Schutz vor solchen Fehlern beitragen.

Dan Guzman
quelle
16

Mit SQL Server können Sie viele dumme Dinge tun.

Sie können sogar einen Fremdschlüssel für eine Spalte erstellen, die auf sich selbst verweist - trotz der Tatsache, dass dies niemals verletzt werden kann, da jede Zeile die Einschränkung für sich selbst erfüllt.

Ein Randfall, in dem die Möglichkeit, zwei Fremdschlüssel in derselben Beziehung zu erstellen, möglicherweise nützlich wäre, besteht darin, dass der zur Überprüfung von Fremdschlüsseln verwendete Index zum Zeitpunkt der Erstellung bestimmt wird. Wenn später ein besserer (dh engerer) Index hinzukommt, kann auf diese Weise eine neue Fremdschlüsseleinschränkung erstellt werden, die an den besseren Index gebunden ist, und die ursprüngliche Einschränkung wird gelöscht, ohne dass eine Lücke ohne aktive Einschränkung besteht.

(Wie im folgenden Beispiel)

CREATE TABLE T1(
    T1_Id INT PRIMARY KEY CLUSTERED  NOT NULL,
    Filler CHAR(4000) NULL,
) 

INSERT INTO T1 VALUES (1, '');

CREATE TABLE T2(
    T2_Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    T1_Id INT NOT NULL CONSTRAINT FK REFERENCES T1 (T1_Id), 
    Filler CHAR(4000) NULL,
)


ALTER TABLE T1 ADD CONSTRAINT
    UQ_T1 UNIQUE NONCLUSTERED(T1_Id) 


/*Execution Plan uses clustered index*/ 
INSERT INTO T2 VALUES (1,1) 

ALTER TABLE T2  WITH CHECK ADD  CONSTRAINT FK2 FOREIGN KEY(T1_Id)
REFERENCES T1 (T1_Id)    

ALTER TABLE T2 DROP CONSTRAINT FK

/*Now Execution Plan now uses non clustered index*/    
INSERT INTO T2 VALUES (1,1)    

DROP TABLE  T2, T1;

Abgesehen von der Zwischenzeit werden alle Einfügungen für beide Indizes validiert, solange beide Einschränkungen bestehen.

Martin Smith
quelle
13

Es hat keinen Sinn, identische Fremdschlüsseleinschränkungen zu haben, dh für dieselben Spalten und für dieselben Tabellen und Spalten.

Es ist, als hätte man den gleichen Scheck 2 oder mehrmals.

ypercubeᵀᴹ
quelle
-Nicht zustimmen. Es besteht die Möglichkeit, dass die Primärtabelle zwei separate Prüfungen benötigt. Siehe unten Beispiel Sender und Empfänger sind völlig unterschiedlich - stackoverflow.com/questions/40400483/…
trex
@ Trex Sie sprechen über etwas anderes. Die Frage hier lautet: "Ich möchte wissen, was es nützt, mehrere Fremdschlüssel zu haben, die in derselben Spalte definiert sind und auf dieselbe Spalte in einer anderen Tabelle verweisen ."
ypercubeᵀᴹ
@ ypercubeᵀᴹ - Verstanden. Vielen Dank für die
Klarstellung
5

Aus demselben Grund können Sie 50 Indizes in derselben Spalte erstellen, eine zweite Protokolldatei hinzufügen, den maximalen Serverspeicher auf 20 MB festlegen. Die meisten Benutzer tun diese Dinge nicht, aber es kann legitime Gründe geben, sie gelegentlich auszuführen Nutzen Sie den Overhead im Motor, um Überprüfungen gegen Dinge hinzuzufügen, die nur schlecht beraten sind.

Aaron Bertrand
quelle
2

Klingt nach einem blaugrünen Ding.

Wenn Sie anfangen, von blau nach grün zu wechseln, müssen Sie vorübergehend zusätzliche Kopien von Dingen erstellen.

Wir möchten vorübergehend einen zusätzlichen Fremdschlüssel erstellen CHECK WITH NOCHECKund ON UPDATE CASCADE ON DELETE SET NULL; Dies ist ein funktionierender Fremdschlüssel, aber die vorhandenen Zeilen werden beim Erstellen des Schlüssels nicht überprüft.

Später, nachdem wir alle Zeilen bereinigt haben, die übereinstimmen sollten, erstellen wir den neuen Fremdschlüssel ohne Befehlsoptionen (standardmäßig ist dies CHECK WITH CHECKdas, was Sie normalerweise möchten) und löschen den temporären Fremdschlüssel.

Beachten Sie, dass beim Löschen und Neuerstellen des Fremdschlüssels einige Müllzeilen an Ihnen vorbeiziehen können.

Joshua
quelle