L'uso di più chiavi esterne sulla stessa colonna in SQL Server


10

SQL Server mi consente di creare più chiavi esterne su una colonna e ogni volta usando solo un nome diverso posso creare un'altra chiave che fa riferimento allo stesso oggetto. Fondamentalmente tutte le chiavi stanno definendo la stessa relazione. Voglio sapere a che serve avere più chiavi esterne che sono definite sulla stessa colonna e che fanno riferimento alla stessa colonna in un'altra tabella. Qual è il vantaggio che SQL Server ci consente di fare una cosa del genere?

inserisci qui la descrizione dell'immagine

Risposte:


12

Non vi è alcun vantaggio nell'avere vincoli ridondanti che differiscono solo per nome. Allo stesso modo, non vi è alcun vantaggio nell'avere indici ridondanti che differiscono solo per nome. Entrambi aggiungono costi generali senza valore.

Il motore di database di SQL Server non ti impedisce di farlo. Le buone convenzioni di denominazione dei vincoli (ad es. FK_ReferencingTable_ReferencedTable) possono aiutare a proteggerne uno da tali errori.


17

SQL Server ti consente di fare molte cose stupide.

Puoi persino creare una chiave esterna su una colonna che fa riferimento a se stessa , nonostante ciò non possa mai essere violato poiché ogni riga soddisfa il vincolo su se stessa.

Un caso limite in cui la possibilità di creare due chiavi esterne sulla stessa relazione sarebbe potenzialmente utile è perché l'indice utilizzato per la convalida delle chiavi esterne è determinato al momento della creazione. Se un indice migliore (cioè più stretto) si presenta in un secondo momento, ciò consentirebbe di creare un nuovo vincolo di chiave esterna associato all'indice migliore e quindi il vincolo originale verrà eliminato senza alcun gap senza alcun vincolo attivo.

(Come nell'esempio seguente)

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;

A parte il periodo intermedio, mentre esistono entrambi i vincoli, tutti gli inserti finiscono per essere convalidati rispetto a entrambi gli indici.


È possibile utilizzare una transazione per garantire lo stesso aggiornamento del vincolo gapless? Questo metodo non di transazione è forse migliore a causa del minor blocco?
binki,

13

Non è utile avere vincoli di chiave esterna identici, ovvero su stesse colonne e facendo riferimento alla stessa tabella e colonne.

È come avere lo stesso controllo 2 o più volte.


-Non sono d'accordo. È possibile che la tabella primaria richieda due controlli separati. Vedere qui esempio mittente e il destinatario sono completamente diversi - stackoverflow.com/questions/40400483/...
trex

@trex stai parlando di qualcosa di diverso. La domanda qui afferma: "Voglio sapere a che serve avere più chiavi esterne che sono definite sulla stessa colonna e riferimento alla stessa colonna in un'altra tabella ".
ypercubeᵀᴹ

@ ypercubeᵀᴹ - Capito. Grazie per averlo chiarito
Trex

6

Stesso motivo per cui puoi creare 50 indici sulla stessa colonna, aggiungere un secondo file di registro, impostare la memoria massima del server su 20 MB ... la maggior parte delle persone non farà queste cose, ma ci possono essere motivi legittimi per farle di tanto in tanto, quindi non c'è beneficio nel creare spese generali nel motore per aggiungere controlli a cose che sono semplicemente sconsiderate.


2

Sembra una cosa blu-verde.

Quando inizi a passare dal blu al verde, devi creare temporaneamente copie extra delle cose.

Quello che vogliamo fare è creare temporaneamente una chiave esterna aggiuntiva CHECK WITH NOCHECKe ON UPDATE CASCADE ON DELETE SET NULL; ciò che fa è che è una chiave esterna funzionante ma le righe esistenti non vengono controllate al momento della creazione della chiave.

Successivamente, dopo aver ripulito tutte le righe che devono corrispondere, creeremo la nuova chiave esterna senza alcuna opzione di comando (l'impostazione predefinita CHECK WITH CHECKè ciò che si desidera in genere) e elimineremo la chiave esterna temporanea.

Nota che se hai appena lasciato cadere e ricreato la chiave esterna, alcune file di immondizia potrebbero scivolare via da te.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.