SQL Server 如何为外键引用选择索引键?

8kb*_*8kb 9 index sql-server primary-key sql-server-2008-r2

我正在使用从 MS Access 导入的旧数据库。在 MS Access > SQL Server 升级过程中创建了大约 20 个带有非集群唯一主键的表。

其中许多表还具有唯一的非聚集索引,它们是主键的副本。

我正在尝试清理它。

但是我发现在我将主键重新创建为聚集索引,然后尝试重建外键后,外键引用了旧的重复索引(这是唯一的)。

我知道这一点,因为它不会让我删除重复的索引。

我认为 SQL Server 会始终选择一个主键,如果存在的话。SQL Server 是否有在唯一索引和主键之间进行选择的方法?

要复制问题(在 SQL Server 2008 R2 上):

IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Child') DROP TABLE Child
GO
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'Parent') DROP TABLE Parent
GO

-- Create the parent table
CREATE TABLE Parent (ParentID INT NOT NULL IDENTITY(1,1)) 

-- Make the parent table a heap
ALTER TABLE Parent ADD CONSTRAINT PK_Parent PRIMARY KEY NONCLUSTERED (ParentID) 

-- Create the duplicate index on the parent table
CREATE UNIQUE NONCLUSTERED INDEX IX_Parent ON Parent (ParentID) 

-- Create the child table
CREATE TABLE Child  (ChildID  INT NOT NULL IDENTITY(1,1), ParentID INT NOT NULL ) 

-- Give the child table a normal PKey
ALTER TABLE Child ADD CONSTRAINT PK_Child PRIMARY KEY CLUSTERED (ChildID) 

-- Create a foreign key relationship with the Parent table on ParentID
ALTER TABLE Child ADD CONSTRAINT FK_Child FOREIGN KEY (ParentID) 
REFERENCES Parent (ParentID) ON DELETE CASCADE NOT FOR REPLICATION

-- Try to clean this up
-- Drop the foreign key constraint on the Child table
ALTER TABLE Child DROP CONSTRAINT FK_Child

-- Drop the primary key constraint on the Parent table
ALTER TABLE Parent DROP CONSTRAINT PK_Parent

-- Recreate the primary key on Parent as a clustered index
ALTER TABLE Parent ADD CONSTRAINT PK_Parent PRIMARY KEY CLUSTERED (ParentID) 

-- Recreate the foreign key in Child pointing to parent ID
ALTER TABLE Child ADD CONSTRAINT FK_Child FOREIGN KEY (ParentID) 
REFERENCES Parent (ParentID) ON DELETE CASCADE NOT FOR REPLICATION

-- Try to drop the duplicate index on Parent 
DROP INDEX IX_Parent ON Parent 
Run Code Online (Sandbox Code Playgroud)

错误消息:

消息 3723,级别 16,状态 6,第 36 行 索引“Parent.IX_Parent”上不允许显式 DROP INDEX。它用于 FOREIGN KEY 约束强制执行。

Jon*_*gel 7

(缺乏)文档表明此行为是一个实现细节,因此未定义且随时可能更改。

这与CREATE FULLTEXT INDEX形成鲜明对比,您必须指定要附加到的索引的名称 - AFAIK,没有未记录的FOREIGN KEY语法来执行等效操作(尽管理论上,将来可能会有)。

如前所述,SQL Server 选择与外键关联的最小物理索引确实有意义。如果您更改脚本以将唯一约束创建为CLUSTERED,则该脚本在 2008 R2 上“有效”。但该行为仍未定义,不应依赖。

与大多数遗留应用程序一样,您只需要深入了解细节并进行清理。