O uso de várias chaves estrangeiras na mesma coluna no SQL Server


10

O SQL Server me permite criar várias chaves estrangeiras em uma coluna e, sempre que usando um nome diferente, posso criar outra referência de chave para o mesmo objeto. Basicamente, todas as chaves estão definindo o mesmo relacionamento. Quero saber para que serve ter várias chaves estrangeiras definidas na mesma coluna e fazer referência à mesma coluna em outra tabela. Qual é o benefício do SQL Server nos permitir fazer algo assim?

insira a descrição da imagem aqui

Respostas:


12

Não há benefício em ter restrições redundantes que diferem apenas pelo nome. Da mesma forma, não há benefício em ter índices redundantes que diferem apenas pelo nome. Ambos adicionam sobrecarga sem valor.

O mecanismo de banco de dados do SQL Server não impede que você faça isso. Uma boa nomeação de restrições As convenções de nomenclatura de restrições (por exemplo, FK_ReferencingTable_ReferencedTable) podem ajudar a proteger alguém contra esses erros.


17

O SQL Server permite que você faça muitas coisas tolas.

Você pode até criar uma chave estrangeira em uma coluna que faz referência a si mesma - apesar do fato de que isso nunca pode ser violado, pois todas as linhas atendem à restrição em si mesmas.

Um caso extremo em que a capacidade de criar duas chaves estrangeiras no mesmo relacionamento seria potencialmente útil é porque o índice usado para validar chaves estrangeiras é determinado no momento da criação. Se um índice melhor (ou seja, mais estreito) aparecer mais tarde, isso permitirá que uma nova restrição de chave estrangeira seja criada vinculada ao melhor índice e, em seguida, a restrição original será eliminada sem que haja nenhuma lacuna sem restrição ativa.

(Como no exemplo abaixo)

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;

Como um aparte para o período intermediário, enquanto ambas as restrições existem, quaisquer inserções acabam sendo validadas nos dois índices.


Uma transação poderia ser usada para garantir a mesma atualização de restrição contínua? Esse método de não transação é melhor devido a menos bloqueio, talvez?
binki 29/03

13

Não há utilidade em ter restrições de chave estrangeira idênticas., Que estão nas mesmas colunas e referenciam as mesmas tabelas e colunas.

É como ter o mesmo cheque 2 ou mais vezes.


-Não concordo. Pode haver uma chance de que a tabela principal precise de duas verificações separadas. Veja abaixo o exemplo remetente e destinatário são totalmente diferentes - stackoverflow.com/questions/40400483/…
trex

@exex você está falando de algo diferente. A pergunta aqui afirma: "Quero saber de que serve ter várias chaves estrangeiras definidas na mesma coluna e fazer referência à mesma coluna em outra tabela ".
ypercubeᵀᴹ

@ ypercubeᵀᴹ - Entendi. Obrigado por deixar claro
trex 14/02

6

Pelo mesmo motivo, você pode criar 50 índices na mesma coluna, adicionar um segundo arquivo de log, definir a memória máxima do servidor para 20 MB ... a maioria das pessoas não faz essas coisas, mas pode haver razões legítimas para fazê-las ocasionalmente, portanto não há benefício na criação de sobrecarga no mecanismo para adicionar verificações contra coisas que são meramente desaconselhadas.


2

Soa como uma coisa verde-azulada.

Quando você começa a mudar de azul para verde, é necessário criar temporariamente cópias extras das coisas.

O que queremos fazer é criar temporariamente uma chave estrangeira extra CHECK WITH NOCHECKe ON UPDATE CASCADE ON DELETE SET NULL; o que isso faz é que é uma chave estrangeira ativa, mas as linhas existentes não são verificadas quando a chave é criada.

Mais tarde, depois de limpar todas as linhas que devem corresponder, criaríamos a nova chave estrangeira sem nenhuma opção de comando (o padrão é o CHECK WITH CHECKque você normalmente deseja) e soltar a chave estrangeira temporária.

Observe que, se você soltar e recriar a chave estrangeira, algumas linhas de lixo poderão passar despercebidas por você.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.