SQL Server 2005: 可空外键约束

15
我在Sessions和Users表之间设置了外键约束,具体来说是Sessions.UID = Users.ID。有时我想让Sessions.UID为null。这可能被允许吗?每次我尝试这样做,都会出现FK Constraint Violation错误。
具体而言,我通过LINQ向Sessions中插入一行数据。我将Session.User = null;设置为null,然后就会出现以下错误:
尝试移除User和Session之间的关系,但是关系之一的外键(Session.UID)不能设置为null。
然而,当我删除将User属性设置为null的行时,在SubmitChanges行上却出现以下错误:
Value cannot be null.
Parameter name: cons
我的任何一个表都没有名为“cons”的字段,它也不在我的5,500行的DataContext.designer.cs文件中,也不在任何相关对象的QuickWatch中,所以我不知道“cons”是什么。
在数据库中,Session.UID是可空的int字段,而User.ID是非空的int字段。我想记录可能有UID的会话,也可能没有,而且我宁愿不禁用FK关系上的约束。有没有办法做到这一点?
1个回答

27

我似乎记得以前创建过可空的外键,所以我进行了一个快速测试。如下所示,它肯定是可行的(在 MSSQL 2005 上测试过)。

将您表格和约束的相关部分脚本化并发布,以便我们可以进一步排除故障。

CREATE DATABASE [NullableFKTest]
GO
USE [NullableFKTest]
GO
CREATE TABLE OneTable 
(
    OneId  [int] NOT NULL,
    CONSTRAINT [PK_OneTable] PRIMARY KEY CLUSTERED 
    (
        [OneId] ASC
    )
)
CREATE TABLE ManyTable (ManyId  [int] IDENTITY(1,1) NOT NULL, OneId [int] NULL)
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_ManyTable_OneTable]') AND parent_object_id = OBJECT_ID(N'[dbo].[ManyTable]') )
ALTER TABLE [dbo].[ManyTable]  WITH CHECK ADD CONSTRAINT [FK_ManyTable_OneTable] FOREIGN KEY([OneId])
    REFERENCES [dbo].[OneTable] ([OneId])   
GO

--let's get a value in here
insert into OneTable(OneId) values(1)
select* from OneTable

--let's try creating a valid relationship to the FK table OneTable
insert into ManyTable(OneId) values (1) --fine
--now, let's try NULL
insert into ManyTable(OneId) values (NULL) --also fine
--how about a non-existent OneTable entry?
insert into ManyTable(OneId) values (5) --BOOM! - FK violation

select* from ManyTable
--1, 1
--2, NULL

--cleanup
ALTER TABLE ManyTable DROP CONSTRAINT FK_ManyTable_OneTable
GO
drop TABLE OneTable
GO
drop TABLE ManyTable
GO
USE [Master]
GO
DROP DATABASE NullableFKTest

7
外键的定义是,它是一个表中的值,必须匹配另一个表中的主键值或为 null。 - Alan
1
从逻辑上讲,这是有道理的,对吧?我的理解是:如果我尝试引用另一个表中的记录,请确保引用是有效的。如果我不这样做(NULL),那又有谁在乎呢。 - andrej_k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接