SQL Server中同一列多个外键的使用

ige*_*elr 10 foreign-key sql-server

SQL Server 允许我在一个列上创建多个外键,并且每次使用不同的名称我都可以创建另一个引用同一对象的键。基本上所有的键都定义了相同的关系。我想知道在同一列上定义多个外键并引用另一个表中的同一列有什么用。SQL Server 允许我们做这样的事情有什么好处?

在此处输入图片说明

Mar*_*ith 17

SQL Server 允许你做很多愚蠢的事情。

您甚至可以在引用自身的列上创建外键- 尽管这永远不会被违反,因为每一行都将满足自身的约束。

在同一关系上创建两个外键的能力可能有用的一种边缘情况是,因为用于验证外键的索引是在创建时确定的。如果稍后出现更好的(即更窄的)索引,那么这将允许在更好的索引上创建一个新的外键约束,然后原始约束删除而没有任何间隙,没有活动约束。

(如下例所示)

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;
Run Code Online (Sandbox Code Playgroud)

作为临时期间的旁白,当两个约束都存在时,任何插入最终都会针对两个索引进行验证。


ype*_*eᵀᴹ 13

具有相同的外键约束是没有用的,即在相同的列上并引用相同的表和列。

这就像进行 2 次或更多次相同的检查。


Dan*_*man 12

具有仅在名称上不同的冗余约束没有任何好处。同样,拥有仅在名称上不同的冗余索引也没有任何好处。两者都增加了没有价值的开销。

SQL Server 数据库引擎不会阻止您这样做。良好的约束命名约束命名约定(例如 FK_ReferencingTable_ReferencedTable)可以帮助防止此类错误。


Aar*_*and 6

同样的原因,您可以在同一列上创建 50 个索引、添加第二个日志文件、将最大服务器内存设置为 20MB ……大多数人不会做这些事情,但偶尔也会有正当理由做这些事情,所以没有受益于在引擎中创建开销以添加对仅仅是不明智的事情的检查。