[英]Can a Check constraint relate to another table?
假设我有一个名为ProjectTimeSpan的表(我没有,只是作为示例!)包含StartDate和EndDate列。
我还有另一个名为SubProjectTimeSpan的表,它还包含名为StartDate和EndDate的列,我想在其中设置一个Check 约束,使得无法将 StartDate 和 EndDate 设置为ProjectTimeSpan.StartDate到ProjectTimeSpan.EndDate的“外部”值
一种了解另一个表值的检查约束...
这可能吗?
为了回应您对 GSerg 的回答的评论,这里有一个使用函数的示例检查约束:
alter table YourTable
add constraint chk_CheckFunction
check (dbo.CheckFunction() = 1)
您可以在哪里定义函数,例如:
create function dbo.CheckFunction()
returns int
as begin
return (select 1)
end
该函数允许引用其他表。
您可以创建一个用户定义的函数来执行检查并返回 1 或 0,然后在其上创建一个check
约束,提供项目 ID 和日期作为参数。
将ProjectTimeSpan
表的键与StartDate
和EndDate
列组合成一个复合键,然后将此复合键用作您的SubProjectTimeSpan
表中的外键引用。 这将使您能够在SubProjectTimeSpan
表中编写必要的行级CHECK
约束,例如
CREATE TABLE ProjectTimeSpan
(
project_ID INTEGER NOT NULL UNIQUE, -- key
StartDate DATE NOT NULL,
EndDate DATE NOT NULL,
CHECK (StartDate < EndDate),
UNIQUE (project_ID, StartDate, EndDate) -- compound key
-- other project columns here...
);
CREATE TABLE SubProjectTimeSpan
(
project_ID INTEGER NOT NULL,
StartDate DATE NOT NULL,
EndDate DATE NOT NULL,
FOREIGN KEY (project_ID, StartDate, EndDate)
REFERENCES ProjectTimeSpan (project_ID, StartDate, EndDate)
ON DELETE CASCADE
ON UPDATE CASCADE,
sub_StartDate DATE NOT NULL,
sub_EndDate DATE NOT NULL,
CHECK (sub_StartDate < sub_EndDate),
CHECK (StartDate <= sub_StartDate), -- sub project can't start before main project
CHECK (sub_EndDate <= EndDate) -- sub project can't end after main project
-- other sub project columns here...
);
正如许多答案所示,您当然可以这样做。 但是,您应该知道 SQL Server 似乎对使用 UDF 的CHECK CONSTRAINT
有问题:
https://dba.stackexchange.com/questions/12779/how-are-my-sql-server-constraints-being-bypassed
您需要在父表和子表上添加约束,因为子项目不能超出项目范围,但项目范围也不能移出所有子项目。
在这种情况下,您应该通过事务推迟对上层(Web 服务、应用程序)的约束检查,以确保在对两个表进行多次查询后您的数据处于有效状态!
这是绝对可能的,而且实际上非常简单。 根据你的例子:
create or alter function dbo.Check_SubProjectTimeSpan_ProjectTimeSpan_Dates(
@ProjectTimeSpanId int
, @StartDate date
, @EndDate date
)
returns bit
as
begin
if exists (select *
from dbo.ProjectTimeSpan as pts
where pts.Id = @ProjectTimeSpanId
and pts.StartDate >= @StartDate
and pts.EndDate <= @EndDate)
begin
return 1
end
return 0
end
go
alter table dbo.SubProjectTimeSpan add constraint
CK_SubProjectTimeSpan_ProjectTimeSpan_ProjectTimeSpanId_StartDate_EndDate
check (
dbo.Check_SubProjectTimeSpan_ProjectTimeSpan_Dates(
ProjectTimeSpanId, StartDate, EndDate) = 1
)
但是请注意,这不会特别有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.