Sql-Server

SQL Server 如何為外鍵引用選擇索引鍵?

  • May 31, 2019

我正在使用從 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 

錯誤資訊:

消息 3723,級別 16,狀態 6,第 36 行索引“Parent.IX_Parent”上不允許顯式 DROP INDEX。它被用於 FOREIGN KEY 約束強制執行。

(缺乏)文件表明此行為是一個實現細節,因此未定義並且隨時可能更改。

這與 CREATE FULLTEXT INDEX 形成鮮明對比,在CREATE FULLTEXT INDEX中,您必須指定要附加到的索引的名稱——AFAIK,沒有未記錄FOREIGN KEY的語法可以執行等效操作(儘管理論上,將來可能會有)。

如前所述,SQL Server 選擇與外鍵關聯的最小物理索引是有意義的。如果您更改腳本以將唯一約束創建為CLUSTERED,則該腳本在 2008 R2 上“有效”。但是這種行為仍然是未定義的,不應依賴。

與大多數遺留應用程序一樣,您只需要深入了解細節並清理乾淨即可。

引用自:https://dba.stackexchange.com/questions/20168