簡體   English   中英

是否可以將非主鍵設置為另一個表中的外鍵?

[英]Is it possible to set a non primary key as foreign key in another table?

更具體地說,我想將AspNetUsers表中的Email列設置為另一個表中的外鍵。

我希望能很好地解釋我的問題。

是和否

SQL Server,特別是:

如果您只是詢問 SQL Server(而不是實體框架),那么我引用Microsoft 的文檔

外鍵約束不必只鏈接到另一個表中的主鍵約束。 也可以定義外鍵以引用另一個表中的 UNIQUE 約束的列。

因此,直接回答您提出的問題:

  • 是否可以將非主鍵設置為另一個表中的外鍵?
    • 如果它們是“普通”列,則否,否則 SQL Server 無法知道這些值將唯一標識每一行。
    • 但是,如果列位於UNIQUE CONSTRAINT或應用了未過濾的UNIQUE INDEX ,則是的,您可以。
    • 這需要 SQL Server 2005 或更高版本。 (我可能錯了,但我不相信 SQL Server 2000 支持引用UNIQUE CONSTRAINT列的FOREIGN KEY約束列。

UNIQUE CONSTRAINTUNIQUE INDEX之間存在細微差別,但主要區別在於表明意圖- 因此當您使用一列或多列作為輔助鍵時,您應該更喜歡UNIQUE CONSTRAINT不是UNIQUE INDEX

實體框架

  • 實體框架 6

    • 我承認我不確定。 我記得必須真正與 EF6 抗爭,並使用VIEW變通辦法使 EF6 在 FK 引用UNIQUE KEY約束時更好玩,但一些報告表明現代版本的 EF6確實支持這一點。
  • 實體框架核心

    • 是的。 使用HasPrincipal()HasForeignKey()來定義兩個輔助鍵TPrincipal和外鍵TDependant指向該次級鍵。

至於你的場景,特別是: dbo.AspNetUsers

假設您想使用Email列來唯一標識用戶,那么我建議您不要這樣做:一般來說,使用可變數據(即可以更改的數據)作為鍵是一個壞主意。 鍵必須是唯一的,理想情況下應該是不可變的 - 雖然電子郵件地址在某些情況下可以是唯一的(例如,您的系統不允許多個用戶共享同一個電子郵件地址),但它們不是一成不變的(用戶可以並更改電子郵件地址)。

另一個警告:為了使用UNIQUE CONSTRAINTUNIQUE INDEX作為外鍵目標,那么這些列不能被過濾或有NULL s - 但dbo.AspNetUser.Emailnvarchar(256) NULL ,所以你會需要確保所有的用戶都有不同的電子郵件地址,首先設置。

話雖如此,這將起作用:

-- 1. Change `Email` from `NULL` to a `NOT NULL` column, as `UNIQUE CONSTRAINT` columns cannot contain duplicates or nulls:
ALTER TABLE dbo.AspNetUsers
    ALTER COLUMN [Email] nvarchar(256) NOT NULL;

-- 2. Create a UNIQUE CONSTRAINT over the `Email` column, so SQL Server knows every row has a distinct value in that column:
ALTER TABLE dbo.AspNetUsers
    ADD CONSTRAINT UQ_Email UNIQUE ( Email );

-- 3. Create a new table with a FOREIGN KEY in the other table:
CREATE TABLE dbo.OtherTable (
    Etc       nvarchar(50) NOT NULL,
    UserEmail nvarchar(256) NULL,
    
    CONSTRAINT FK_Users_by_email FOREIGN KEY ( UserEmail ) REFERENCES dbo.AspNetUsers ( [Email] )
);

是的,您可以使用 fluent api 通過 asp.net core 中的主鍵創建外鍵。 您可以從此處查看來自 microsoft doc 的示例

我能夠為非 pk 列創建外鍵。 沒有問題。

CREATE TABLE [dbo].[t1](
[id] [int] NOT NULL,
[fldKey] [int] NULL,
CONSTRAINT [PK_t1] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[t2](
[id] [int] NOT NULL,
[t1] [int] NULL,
CONSTRAINT [PK_t2] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[t2]  WITH CHECK ADD  CONSTRAINT [FK_t2_t1] FOREIGN 
KEY([t1])
REFERENCES [dbo].[t1] ([fldKey])
GO
ALTER TABLE [dbo].[t2] CHECK CONSTRAINT [FK_t2_t1]
GO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM